依赖收集阶段最重要的目的 , 就是建立一份”依赖收集表“ , 也就是图示的”targetMap" 。targetMap 是一个 WeakMap , 其 key 值是~~当前的 Proxy 对象 state~~代理前的对象origin , 而 value 则是该对象所对应的 depsMap 。
depsMap 是一个 Map , key 值为触发 getter 时的属性值(此处为 count) , 而 value 则是触发过该属性值所对应的各个 effect 。
还是有点绕?那么我们再举个例子 。假设有个 Proxy 对象和 effect 如下:
const state = reactive({count: 0,age: 18})const effect1 = effect(() => {console.log('effect1: ' + state.count)})const effect2 = effect(() => {console.log('effect2: ' + state.age)})const effect3 = effect(() => {console.log('effect3: ' + state.count, state.age)})复制代码那么这里的 targetMap 应该为这个样子:

文章插图
这样 , { target -> key -> dep } 的对应关系就建立起来了 , 依赖收集也就完成了 。代码如下:
export function track (target, operationType, key) {const effect = effectStack[effectStack.length - 1]if (effect) {let depsMap = targetMap.get(target)if (depsMap === void 0) {targetMap.set(target, (depsMap = new Map()))}let dep = depsMap.get(key)if (dep === void 0) {depsMap.set(key, (dep = new Set()))}if (!dep.has(effect)) {dep.add(effect)}}}弄明白依赖收集表 targetMap 是非常重要的 , 因为这是整个响应式系统核心中的核心 。响应阶段回顾上一章节的例子 , 我们得到了一个 { count: 0, age: 18 } 的 Proxy , 并构造了三个 effect 。在控制台上看看效果:

文章插图
效果符合预期 , 那么它是怎么实现的呢?首先来看看这个阶段的原理图:

文章插图
当修改对象的某个属性值的时候 , 会触发对应的 setter 。
setter 里面的 trigger() 函数会从依赖收集表里找到当前属性对应的各个 dep , 然后把它们推入到 effects 和 computedEffects(计算属性) 队列中 , 最后通过 scheduleRun() 挨个执行里面的 effect 。
由于已经建立了依赖收集表 , 所以要找到属性所对应的 dep 也就轻而易举了 , 可以看看具体的代码实现:
export function trigger (target, operationType, key) {// 取得对应的 depsMapconst depsMap = targetMap.get(target)if (depsMap === void 0) {return}// 取得对应的各个 depconst effects = new Set()if (key !== void 0) {const dep = depsMap.get(key)dep && dep.forEach(effect => {effects.add(effect)})}// 简化版 scheduleRun , 挨个执行 effecteffects.forEach(effect => {effect()})}复制代码这里的代码没有处理诸如数组的 length 被修改的一些特殊情况至此 , 响应式阶段完成 。
总结阅读源码的过程充满了挑战性 , 但同时也常常被 Vue 的一些实现思路给惊艳到 , 收获良多 。本文按照响应式系统的运行过程 , 划分了”初始化“ , ”依赖收集“和”响应式“三个阶段 , 分别阐述了各个阶段所做的事情 , 应该能够较好地帮助读者理解其核心思路 。
推荐阅读
- 彻底解决MySQL中的乱码问题
- 请记住,讨厌一个人不必翻脸,掌握这3点巧妙化解尴尬
- 这些不着眼的Excel小技巧,看看你掌握了没?
- 祛斑小妙招,你掌握了没
- 祛斑除皱小窍门,你需要掌握这些
- 带你玩转MySQL,索引揭秘,看我是如何让你的查询性能指数提升的
- 掌握红色服饰的搭配技巧,轻松佩戴起首饰,让你在聚会中大放光彩
- 手把手带你搭建一个自己的云服务器并部署Web程序
- MacOS上的这些隐藏技巧,一旦掌握,爱不释手!
- 离婚前如何掌握对方所有财产,教你三招,财产一览无余,建议收藏
