例子
import { ref, watchEffect } from 'vue'
const A0 = ref(0)
const A1 = ref(1)
const A2 = ref()
watchEffect(() => {
// 追踪 A0 和 A1
A2.value = A0.value + A1.value
})
// 将触发副作用
A0.value = 2
1. 首先对一个变量进行代理,去监控它的 读取 和 写入 操作,这里监控的是 A0, A1, A2
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
track(target, key) // 读取后进行的操作
return target[key]
},
set(target, key, value) {
target[key] = value // 写入后进行的操作
trigger(target, key)
}
})
}
function ref(value) {
const refObject = {
get value() {
track(refObject, 'value')
return value
},
set value(newValue) {
value = newValue
trigger(refObject, 'value')
}
}
return refObject
}
2. 当运行 watchEffect 时,watchEffct 相当于这个函数,会将里面的函数(副作用函数)赋值到 activeEffect,再执行里面的函数
function whenDepsChange(update) {
const effect = () => {
activeEffect = effect
update()
activeEffect = null
}
effect()
}
执行里面的函数后会读取 A0 和 A1, 就会进到 get 里面的 track() 函数中去。因为前面已经赋值 activeEffect 了,所以这个是有值的,会将这个 activeEffect 放到对应 A0 和 A1 的 Set 里面去
// 这会在一个副作用就要运行之前被设置
// 我们会在后面处理它
let activeEffect
function track(target, key) {
if (activeEffect) {
const effects = getSubscribersForProperty(target, key)
effects.add(activeEffect)
}
}
3. 这样,当 A0 或者 A1 做写入操作的时候,会触发 set 中的 trigger,把 Set 中的 副作用函数再执行一遍,就能做到响应式更新