Vue3 watchEffect 源码学习
2024-01-04 14:49:55
前言
在看 reactive 源码的时候发现单独调用 reactive 函数并没有收集依赖,那么什么时候才会收集依赖呢,我把之前的 demo 改了改,加入了 watchEffect 之后发现 watchEffect 在调用的时候会触发 get 的时候把当前的 effect 函数收集起来,而当数据被修改的时候会遍历这个 effect 数组,分别执行这些 effect,这样就能实现响应式的功能了,具体实现原理我来带大家看一下源码吧。
watchEffect 源码分析
1. 准备工作
首先,我们需要创建一个 watchEffect 函数,这个函数将被用来跟踪依赖项并更新视图。
function watchEffect(callback) {
// 创建一个 effect 实例
const effect = createEffect(callback)
// 立即执行 effect
effect()
// 返回一个 cleanup 函数,用于取消 effect
return effect.stop
}
2. createEffect 函数
createEffect 函数是 Vue3 中用于创建 effect 的函数。它接受一个 callback 函数作为参数,该函数将在每次数据发生变化时被调用。
function createEffect(callback) {
// 创建一个 effect 对象
const effect = {
// effect 函数
callback,
// 是否正在运行
active: true,
// 收集的依赖项
deps: [],
// 停止 effect 的函数
stop() {
// 将 active 设为 false,以停止 effect
effect.active = false
// 从所有依赖项中移除 effect
for (const dep of effect.deps) {
dep.delete(effect)
}
}
}
// 将 effect 添加到全局 effect 数组中
globalEffects.add(effect)
// 返回 effect
return effect
}
3. get 函数
get 函数是 Vue3 中用于获取响应式数据的函数。它接受一个对象和一个属性名称作为参数,并返回该属性的值。
function get(target, key) {
// 获取对象的原始值
const value = Reflect.get(target, key)
// 如果对象的属性是响应式的,则收集依赖项
if (isReactive(value)) {
// 从 effect 数组中取出最后一个 effect
const effect = globalEffects.last()
// 将 effect 添加到属性的依赖项数组中
value.deps.add(effect)
// 将属性添加到 effect 的依赖项数组中
effect.deps.add(value)
}
// 返回对象的原始值
return value
}
4. set 函数
set 函数是 Vue3 中用于设置响应式数据的函数。它接受一个对象、一个属性名称和一个新值作为参数,并设置该属性的新值。
function set(target, key, value) {
// 设置对象的原始值
const oldValue = Reflect.get(target, key)
Reflect.set(target, key, value)
// 如果对象的属性是响应式的,则触发依赖项
if (isReactive(oldValue)) {
// 从 effect 数组中取出最后一个 effect
const effect = globalEffects.last()
// 触发 effect 的依赖项
effect.deps.forEach(dep => dep.run())
}
}
5. 使用 watchEffect
现在,我们已经了解了 watchEffect 的源码,就可以开始使用它了。
const app = Vue.createApp({
data() {
return {
count: 0
}
},
watch: {
count(newValue, oldValue) {
console.log(`count changed from ${oldValue} to ${newValue}`)
}
}
})
app.mount('#app')
这段代码创建一个 Vue 实例,并使用 watchEffect 来跟踪 count 属性的变化。每次 count 属性发生变化时,都会调用 watchEffect 的 callback 函数,并打印出 count 属性的新值和旧值。
总结
以上就是 Vue3 watchEffect 源码的实现原理。通过这篇文章,我们了解了 watchEffect 是如何收集和追踪依赖,以及如何实现响应式更新的。同时,我们还学习了一些有关如何使用 watchEffect 的建议,希望这些建议能够帮助您在开发中更好地利用 watchEffect。