开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情
Vue3 Watch 源码实现
在Vue3中,watch的实现方式有所不同,使用了新的API watchEffect和watch。
下面我们来详细了解一下它们的实现原理。
watchEffect
watchEffect是一个立即执行的响应式副作用函数,用于执行响应式数据的副作用和响应式数据的收集。
每一次响应式数据的变化都会重新执行该函数。
watchEffect实际上是watch的特殊形式,只监听其所使用的响应式数据,不需要手动指定监听的响应式数据。
下面是watchEffect的核心实现代码:
function watchEffect(effect) {
// 创建响应式副作用函数
const runner = effect.bind(null, {
get,
run: effect
})
// 第一次执行副作用函数
runner()
// 收集响应式数据
return () => {
stop(runner)
}
}
从上面的代码可以看出,watchEffect的实现分为两个步骤:
- 创建响应式副作用函数
- 收集响应式数据
其中,第一步是通过bind方法创建一个响应式副作用函数,并且将get方法和当前副作用函数绑定到一个对象上,以便在副作用函数内部可以使用get方法获取响应式数据。
第二步是在第一次执行副作用函数时,会自动收集该副作用函数内部所使用的响应式数据。当响应式数据发生变化时,会重新执行该副作用函数,并且重新收集响应式数据。
watch
watch是一个更加灵活的API,可以用于监听一个或多个响应式数据的变化,并在数据变化时执行相应的回调函数。
下面是watch的核心实现代码:
function watch(source, cb, options) {
// 创建一个响应式的getter
const getter = () => source()
// 创建一个响应式副作用函数
const runner = effect(getter, {
lazy: true,
...options
})
// 执行回调函数
let oldValue = undefined
runner.onTrack = () => {
oldValue = runner()
}
runner.onTrigger = () => {
const newValue = runner()
cb(newValue, oldValue)
oldValue = newValue
}
// 手动执行一次副作用函数
if (options && options.immediate) {
cb(runner(), undefined)
}
// 返回一个停止侦听响应式数据的函数
return () => {
stop(runner)
}
}
从上面的代码可以看出,watch的实现也分为两个步骤:
- 创建响应式副作用函数
- 执行回调函数
其中,第一步是通过创建一个响应式的getter来获取响应式数据,并且创建一个响应式副作用函数来收集响应式数据的变化。
第二步是在响应式数据发生变化时,执行回调函数,并将新旧值作为参数传入回调函数中。
总结
通过实现watchEffect和watch,我们可以更好的理解Vue3中响应式原理的实现方式。
watchEffect可以用于执行响应式数据的副作用和响应式数据的收集
而watch可以用于监听响应式数据的变化并执行相应的回调函数。
Vue3的响应式原理更加高效和灵活,为开发者提供了更好的响应式编程体验。