Vue3 的响应式实现与 Vue2 版本类似,都是在 getter 里收集依赖,setter 触发依赖更新,不同点在:
数据劫持从 Object.defineProperty 变为 Proxy,前者只能劫持存在的对象属性,后者可以劫持任意属性,包括新增的属性,并且支持数组原生方法增删改的响应式。
收集和触发依赖的逻辑有变化,使用了一个全局 Map 对象:
// 代理对象
const person = {name: 'Zhang San', age: 10}
// 全局 Map
const targetDepsMap = new WeakMap()
// 假如外部触发了 person.name 的 getter,则依赖的收集大致是这样的:
// targetDepsMap 将代理对象 person 作为 key,并创建属于他自己的 Map
const personMap = new Map()
targetDepsMap.set(person, personMap)
// personMap 设置 name 为一个集合(用于放 effect 函数)
const personNameSet = new Set()
personMap.set('name', personNameSet)
// 当触发了 person.name 的 getter 时,添加 effect 函数到该集合
personNameSet.add(effect)
实现了 reactive、ref、watchEffect、computed 函数的核心功能。