VUE3的watchEffect使用
VUE2.0大家都是是用过watch,可以监听某个值的变更,可以做一些相应的事件处理。VUE3.0出来一个watchEffect的东西,我们一起看下这个api有什么用途。
与watch有什么区别?
我们先来看一个简单watch的例子
<script lang="ts">
import {
defineComponent, watch, ref,
} from 'vue';
export default defineComponent({
setup() {
const count = ref(0);
watch(count, (val, oldVal) => {
console.log(val, oldVal);
});
setTimeout(() => {
count.value += 1; // 当值改变时执行
}, 1000);
}
});
</script>
再来看一个watchEffect的简单例子
<script lang="ts">
import {
defineComponent, watchEffect, ref,
} from 'vue';
export default defineComponent({
setup() {
const count = ref(0);
watchEffect(() => {
console.log(count.value); // 初始化时会执行一次
});
setTimeout(() => {
count.value += 1; // 值变化时又执行了一次
}, 1000);
}
});
</script>
通过两个简单的例子,我们可以看得出,watch和watchEffect还是有一些区别的
watchEffect
会自动的收集依赖,而watch是明确的指定监听某个变量watch
可以获取到新值和旧值,watchEffect
则只能取到最新的watchEffect
会在初始化的时候执行一次,类似computed
与compute有什么区别?
同样,我们先来看一个例子
<template>
{{sayHello}}
</template>
<script lang="ts">
import {
defineComponent, watchEffect, ref, computed,
} from 'vue';
export default defineComponent({
setup() {
const count = ref(0);
watchEffect(() => {
console.log(count.value);
});
setTimeout(() => {
count.value = 20;
}, 1000);
const name = ref('thomaskwun');
const sayHello = computed(() => {
console.log('computed', count.value);
return `我是${name.value},${count.value}岁`;
});
return {
sayHello,
};
},
});
</script>
computed和watchEffect相同的地方是会自动收集依赖,在值更新时会触发回调,会初始化调用一次。
但是在触发初始化的时机是不一样的,如果computed的值没有被使用,是不会触发回调的,只有在该值被使用的时候才会触发回调,但watchEffect是在setup的时候就会初始化。
根据他们的差异,我们可以在不同的业务场景下选择合适的处理方法。
watchEffect的使用
注意事项
如果watchEffect
涉及到dom或者ref的操作,需要在onMounted
生命周期里调用
停止监听
<script lang="ts">
import {
defineComponent, watchEffect, ref,
} from 'vue';
export default defineComponent({
setup() {
const count = ref(0);
const myWatch = watchEffect(() => {
console.log(count.value);
});
setTimeout(() => {
console.log('change');
count.value = 20;
}, 1000);
myWatch();
},
});
</script>
如果是在setup
的生命周期里声明的watchEffect
,在组件销毁的时候是会默认清除监听,也可以再次调用watchEffect
显式停止监听。
清除副作用
const count = ref(0);
const stop = watchEffect(onInvalidate => {
const token = asyncOperate(count.value);
onInvalidate(() => { // 消除上次的副作用
token.cancel();
})
}
watchEffect进阶
const count = ref(0);
const stop = watchEffect(onInvalidate => {
const token = asyncOperate(count.value);
onInvalidate(() => { // 消除上次的副作用
token.cancel();
})
}, {
flush: "sync", // 副作用的调度机制 sync, pre, post
onTrack: e => { // 调试用: 追踪的信息
console.log(e);
},
onTrigger: e => { // 调试用:响应式信息
console.log(e);
},
})
// 如副作用中设计到DOM的操作和ref的获取,需要放到mounted周期中执行
onMounted(() => {
watchEffect(() => { // .. 操作dom或ref等 })
})
参考资料
https://www.yuque.com/atomjaylee/fe/sm5bst
https://segmentfault.com/a/1190000023669309