Vue3笔记(2)

196 阅读2分钟

Vue.js 3.0 响应式系统的实现原理

内部会维护一个targetMap来记录对象和它的属性,以及属性变化时对应的update更新操作函数。在通过Proxy来进行对象操作进行拦截,拦截get操作时会调用track收集依赖,拦截set、deleteProperty操作时会调用trigger来触发更新

targetMap用来记录对象和属性的映射关系:key为target,value为一个depsMap;depsMap用来记录属性和update更新的一组函数的映射关系:key为访问的属性,value为一个dep的set;这个dep中存放着一组activeEffect,就是更新需要执行的操作

const product = reactive({
    price: 100,
    count: 3
})
let total = 0
effect(() => {
    total = product.price * product.count
})
// 相当于
targetMap => {
    product => depsMap
}
product => depsMap => {
    price => dep
    count => dep
}
price => dep => [ () => {total = product.price * product.count} ]
count => dep => [ () => {total = product.price * product.count} ]

  1. 调用reactive传入需要响应式处理的对象,在内部通过Proxy进行对象操作拦截,返回new Proxy代理的对象
  2. 访问对象属性时,拦截get操作,调用track来收集依赖,再获取属性的值,判断属性的值是不是对象,是就再调用reactive来实现子对象的递归
  3. track接收对象和访问的属性(target, key),先判断当前有没有activeEffect,activeEffect是在effect函数中设置为update处理的回调函数,没有就return;有就继续,用target从targetMap里面获取到depsMap,没有就设置一个新的Map,targetMap.set(target, (depsMap = new Map())),用key从depsMap里面获取到dep,没有就设置一个新的Set,depsMap.set(key, (dep = new Set())),最后把activeEffect添加到dep里dep.add(activeEffect)
  4. 设置或者删除对象属性时,拦截set、deleteProperty操作,调用trigger触发更新
  5. trigger接收对象和访问的属性(target, key),用target从targetMap里面获取depsMap,没有就返回,有再用key从depsMap获取到dep,获取到dep后遍历这个set,每个元素都是track时放进去的activeEffect回调函数,执行来进行更新effect()