watch
- 默认懒执行,数据源变化时才执行一次。如果想要初始进来,立即执行设置 immediate: true
- 设置deep: true 深层遍历(默认浅层监听,只监听顶层的属性变化)。Vue3.5+中,deep可以设置数字,表示最大遍历层数。深度监听有性能开销,谨慎使用
- once: true 只执行一次
- flush: 'post' 回调触发时机。默认情况下,侦听器回调会在父组件更新之后,所属组件DOM更新之前调用
- post: 想让回调函数访问vue更新之后所属组件的DOM
- pre: 默认
- sync: 同步侦听器,在vue进行任何更新之前触发
<script setup>
import { ref, watch } from 'vue'
const value1 = ref('')
const x = ref(0)
const y = ref(0)
const sum = ref(0)
// 1. 监听单个 ref
watch(value1, (newVal, oldVal) => {
console.log(`value1 changed from ${oldVal} to ${newVal}`)
}, {
immediate: true, // 初始进来,立即执行一次
deep: true, // 深层遍历,必要时使用,有性能开销
once: true, // 只执行一次
flush: 'post' // 回调触发时机
})
// 2. 监听getter函数(监听reactive对象的特定属性,或者需要计算派生值时)
// 2.1 监听reactive对象的特定属性
const user = reactive({ name: 'John', age: 25 })
watch(
() => user.name, // 只监听 name 变化
(newName) => {
console.log('用户名变化:', newName)
}
)
// 2.2 计算派生值
watch(
() => x.value + y.value, // 监听计算结果
(sum) => {
console.log(`sum is ${sum}`)
}
)
// 3. 监听多个来源组成的数组,回调函数接收两个数组参数(新值数组、旧值数组)
watch([x, () => y.value], ([newX, newY], [oldX, oldY]) => {
console.log(`x is ${newX}, y is ${newY}`)
})
</script>
<template>
<input ref="my-input" v-model="value1" />
</template>
watchEffect
只监听回调中用到的属性,比深度监听更有效,不会无脑深度遍历所有属性
watchEffect(async () => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/todos/${todoId.value}` // 自动追踪 todoId.value
)
data.value = await response.json()
})
- flush:修改回调触发时机
watchEffect(callback, {
flush: 'post' // ‘sync’
})
// 后置刷新的 watchEffect,有个别名 watchPostEffect
import { watchPostEffect } from 'vue'
watchPostEffect(() => {
/* 在 Vue 更新后执行 */
})
// 同步触发的 watchEffect,有个别名 watchSyncEffect
import { watchSyncEffect } from 'vue'
watchSyncEffect(() => {
/* 在响应式数据变化时同步执行 */
})
watch 和 watchEffect 的区别
- watch:明确追踪指定属性,精确控制回调函数的执行时机。需要比对新旧值时用watch
- watchEffect:同步执行过程中,自动追踪所有能访问到的响应式属性,这更方便、更高效,但有时响应性依赖关系不那么明显