导图大纲
watch
侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数。
watch() 默认是懒侦听的,即仅在侦听源发生变化时才执行回调函数。
watch 有三个参数
第一个参数:
第一个参数是侦听器的源
- 一个函数,返回一个值
- 一个 ref
- 一个响应式对象
- ...或是由以上类型的值组成的数组
第二个参数
第二个参数是在发生变化时要调用的回调函数。
这个回调函数接受三个参数:新值、旧值,以及一个用于注册副作用清理的回调函数。
该回调函数会在副作用下一次重新执行前调用,可以用来清除无效的副作用,例如等待中的异步请求。
当侦听多个来源时,回调函数接受两个数组,分别对应来源数组中的新值和旧值。
代码语言:txt复制watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
/* ... */
})
第三个参数
第三个可选的参数是一个对象;
- immediate:在侦听器创建时立即触发回调。第一次调用时旧值是 undefined。
- deep:如果源是对象,强制深度遍历,以便在深层级变更时触发回调。参考深层侦听器。
- flush:调整回调函数的刷新时机。参考回调的刷新时机及 watchEffect()。
- onTrack / onTrigger:调试侦听器的依赖。参考调试侦听器。
注意
当直接侦听一个响应式对象时,侦听器会自动启用深层模式:
代码语言:txt复制const state = reactive({ count: 0 })
watch(state, () => {
/* 深层级变更状态所触发的回调 */
})
侦听一个 getter 函数:
当 侦听 一个 getter 函数时,回调只在此函数的返回值变化时才会触发,。
如果想让深层对象变化时,也被侦听调用,可以加 { deep: true } 强制侦听器进入深层级模式
代码语言:txt复制const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* ... */
},
{
deep: true
}
)
侦听 一个 ref
代码语言:txt复制const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})
watchEffect()
立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行
watchEffect 接受两个参数
第一个参数
第一个参数是数据发生变化时执行的回调函数
- 当监听的值发生变化时,会自动再次执行以下回调函数
watchEffect(() => {
//监听objData.str
console.log(objData.str)
// 会在 props 变化时打印
console.log(name, phone, age)
//海军 1234567 22
})
第二个参数
第二个参数是一个可选的对象,支持 flush 和 onTrack / onTrigger 选项,功能和 watch 相同。
代码语言:txt复制watchEffect(() => {}, {
flush: 'post',
onTrack(e) {
debugger
},
onTrigger(e) {
debugger
}
})
停止监听
代码语言:txt复制const stop = watchEffect(() => {})
// 当不再需要此侦听器时:
stop()
注意
注意:watchEffect 仅会在其同步执行期间,才追踪依赖。使用异步回调时,只有在第一个 await 之前访问到的依赖才会被追踪。
watch vs watchEffect
两者区别
watch 和 watchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式:
- watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。
<!---->
- watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确。
访问 Vue 更新之后的 DOM
在 Vue2.x 中, 使用 nextTick, 在Vue3 中,watch / watchEffect 指明 flush: 'post' 选项 即可。
代码语言:txt复制watch(source, callback, {
flush: 'post'
})
watchEffect(callback, {
flush: 'post'
})
watchEffect 有个别名 也可以 后置刷新 watchPostEffect();
代码语言:txt复制import { watchPostEffect } from 'vue'
watchPostEffect(() => {
/* 在 Vue 更新后执行 */
})
小技巧
关闭监听器
手动停止一个侦听器,请调用 watch 或 watchEffect 返回的函数:
代码语言:txt复制const stopWatchEffect = watchEffect(() => {
})
stopWatchEffect()
const stopWatch = watch(() => {
})
stopWatch()
异步数据加载
如果需要等待一些异步数据,你可以使用条件式的侦听逻辑:
代码语言:txt复制// 需要异步请求得到的数据
const data = ref(null)
watchEffect(() => {
if (data.value) {
// 数据加载后执行某些操作...
}
})