watch- 默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。
watch- 更明确哪些状态的改变会触发侦听器重新运行副作用;
watch- 获取到侦听状态变化前后的值。
————————————————————
watchEffect 不需要手动传入依赖
watchEffect 会先执行一次用来自动收集依赖
watchEffect 无法获取到变化前的值, 只能获取变化后的值
source: 可以支持 string,Object,Function,Array; 用于指定要侦听的响应式变量
callback: 执行的回调函数
options:支持 deep、immediate 和 flush 选项。
const count= ref(0);
setTimeout(() => {
count.value++;
}, 1000);
watch(count, (newVal, oldVal) => {
console.log("新值:", newVal, "老值:", oldVal);
});
import { defineComponent, ref, reactive, toRefs, watch } from "vue";
export default defineComponent({
setup() {
const state = reactive({ name: "liu", count: 20 });
setTimeout(() => {
state.count++;
}, 1000);
// 修改count值时会触发 watch的回调
watch(
() => state.count,
(curCount, preCount) => {
console.log("新值:", curCount, "老值:", preCount);
}
);
return {
...toRefs(state),
};
},
});
上面两个例子中,我们分别使用了两个 watch, 当我们需要侦听多个数据源时, 使用数组来同时侦听多个源:
watch([() => state.count, count], ([curCount, newVal], [preCount, oldVal]) => {
console.log("新值:", curCount, "老值:", preCount); console.log("新值:", newVal,
"老值:", oldVal); });
我们实际开发中,复杂数据随处可见, 比如:
const state = reactive({
message: {
id: 7,
attrs: {
name: "liu",
count: "1",
},
},
});
watch(
() => state.message,
(newType, oldType) => {
console.log("新值:", newType, "老值:", oldType);
},
{ deep: true }
);
deep: true 表示开启深度监听。(如果不使用第三个参数deep:true
, 是无法监听到数据变化的) immediate: true 无论数据是否发生变化,数据默认执行一次(使watch不为惰性,立即执行回调函数)
当 watch
在组件的 setup()
函数或生命周期钩子被调用时, 侦听器会被链接到该组件的生命周期,并在组件卸载时自动停止。
如果在组件销毁之前我们想要停止掉某个监听, 可以调用watch()
函数的返回值,操作如下:
const stopWatch = watch(() => state.message, (newType, oldType) => {
console.log("新值:", newType, "老值:", oldType);
}, {deep:true});
setTimeout(()=>{
// 停止监听
stopWatch()
}, 2000)
import { defineComponent, ref, reactive, toRefs, watchEffect } from "vue";
export default defineComponent({
setup() {
const state = reactive({ name: "liu", count: 20 });
let count= ref(0)
watchEffect(() => {
console.log(state.count);
console.log(count.value);
}
);
setInterval(() =>{
state.count++
count.value++
},2000)
return {
...toRefs(state)
}
},
});
执行结果首先打印一次state.count
和count
值(默认依赖);然后每隔一秒,打印state.count
和count
值。 从上面的代码可以看出, 并没有像watch
一样需要先传入依赖,watchEffect
会自动收集依赖, 只要指定一个回调函数。在组件初始化时, 会先执行一次来收集依赖, 然后当收集到的依赖中数据发生变化时, 就会再次执行回调函数。
按钮::展示count{{count1}}-{{count2}}
如果副作用需要同步或在组件更新之前重新运行,我们可以传递一个拥有 flush
属性的对象作为选项(默认为 'post'
):
如果没有{ flush:'post' },默认就是先执行监听器,然后更新DOM,此时DOM还未生成,所以是null。--更新DOM,配置flush: 'post'
// 同步运行
watchEffect(
() => {
/* ... */
},
{
flush: 'sync',
}
)
// 组件更新前执行
watchEffect(
() => {
/* ... */
},
{
flush: 'pre',
}
)