如下面一个简单的例子
<script setup lang="ts">
import { watch, ref } from "vue";
const count = ref(0);
watch(count, (newCount) => {
console.log("new count", newCount);
});
</script>
你有没有想过,为什么 watch 不需要像 React Effect hook 一样 return cleanup 函数?
你有没有注意过 Vue 的 watch 其实是 return 了 cleanup (但是却不用你手动调用的)?
好神奇,怎么做到的?
查阅源码,关键代码如下,非常的简单:
function doWatch() {
...
const effect = new ReactiveEffect(getter, NOOP, scheduler)
const scope = getCurrentScope()
const unwatch = () => {
effect.stop()
if (scope) {
remove(scope.effects, effect)
}
}
...
return unwatch
}
魔法在于 const scope = getCurrentScope()
getCurrentScope 取到的是 Vue setup 函数调用时的 EffectScope。
所以像下面这段代码,肯定是不能够按预期执行的:
onMounted(async () => {
await delay(300); // 延迟300ms
watch(domRef, () => {
// balabala
});
});