vue3 监听器,组合式API的watch用法
watch函数
在组合式 API 中,我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数
watch(ref,callback(newValue,oldValue),option:{})
ref:被监听的响应式量,可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组
callback:回调函数,当被监听的响应式量变化是触发回调,callback有两个参数,类型和ref一致,值是捕获到的变化后的ref,和变化前的ref
option: 对象提供一些监听函数的监听参数,比如是否开启深层监听
一个最简单的监听示例
{{ count }}
当按钮点击时count递增,watch函数会捕获count的变化,并触发回调函数打印出count的值
这里 点击了20下每次变化都触发了一次回调
监听getter
sum=
{{ count }}+
{{ obj.num }}
这里不能直接监听响应式对象的值(obj.sum ),而是需要用一个返回该属性的 getter 函数要监听的值( ()=> obj.sum )
深层监听器
深层侦听需要遍历被侦听对象中的所有嵌套的属性,对于一个对象来说,没有深度监听只有当整个对象改变才会被捕获,
虽然不能直接监听响应式对象的值,但是可以直接监听响应式对象,这会隐式的激活深层监听
sum=
{{ count }}+
{{ obj.num }}
const obj = reactive({num:0});
watch( obj, (newValue,oldValue)=>{
console.log(newValue,oldValue);
})
可以看出来回调的两个对象参数它们式相等的两个值,
当你监听对象内嵌套的对象时,则需要手动开启深层监听,否则只有当整个对象改变时才能被捕获
sum=
{{ count }}+
{{ obj.num }}
嵌套对象的属性{{ ob.obj.num }}
const ob = ref({
obj:{
num:0,
str:"hello"
},
count:0
})
watch(()=>ob.value.obj, (newValue,oldValue)=>{
console.log(newValue,oldValue);
},{
deep:true
})
可以看到开启深层监听后就可以捕获到变化响应了
立刻回调和一次回调
{
deep:true,
immediate:true,
once:true
}
除了深层回调还有两个参数,immediate,once,布尔值,它们分别表示,立刻执行一次回调(在开始捕获之前)和只回调一次(只捕获一次响应变化)
watchEffect函数
watchEffect会自动监听能访问到的且发生了响应变化的值,并且只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性,这有时候比深层监听遍历所有属性要更好,但是要注意,它仅会在其同步执行期间,才b捕获响应变化。在使用异步回调时,只有在第一个 await
正常工作前访问到的属性才会被捕获。
watchEffect(callback(newValue,oldValue),option:{})
callback:回调函数,当被监听的响应式量变化是触发回调,callback有两个参数,类型和ref一致,值是捕获到的变化后的ref,和变化前的ref
option: 对象提供一些监听函数的监听参数,
watch
和 watchEffect
watch
和 watchEffect
都能响应式地执行能响应的回调(触发页面变化)。它们之间的主要区别是追踪响应式依赖的方式:
watch:需要提供监听目标,监听属性更加精确,仅在监听的目标变化时触发
watchEffect: 不需要提供监听补码,监听时没有那么明确,自动追踪所有能访问到的(参与回调的)响应式属性。
sum=
{{ count }}+
{{ obj.num }}
嵌套对象的属性{{ ob.obj.num }}
watchEffect((newValue,oldValue)=>{
console.log("捕获到了变化",count.value,"
",newValue,oldValue);
color.value = "red";
})
回调中有count,当count变化时直接被捕获,改变了背景颜色,同时它还默认响应了一个函数
回调触发时机
watchEffect(callback,option:{})
option:
flush:post/sync (指明post,则会在响应后回调,指明sync,则会在响应前回调)
// 或者你可以用对应的函数;
watchPostEffect()
watchSyncEffect()
// 它们的效果是一样的
如果想在侦听器回调中能访问被 Vue 更新之后的所属组件的 DOM,你需要指明 flush: 'post'
或者使用 watchPostEffect()
:
如果想在侦听器回调在 Vue 进行任何更新之前触发:你需要指明 flush: 'sync'
或者使用 watchSyncEffect()
:
停止监听
在 setup()
或
sum=
{{ count }}+
{{ obj.num }}
嵌套对象的属性{{ ob.obj.num }}