29行代码介绍Vue3响应式及依赖收集

原创
前端路迹
2024-11-27 16:50
编辑于 2024-11-27 16:55

29行代码如下(没算空行)。

<div id="log"></div>
<script>
let activeEffect;
let targetMap = {};

const p = new Proxy(
    { x: 1 },
    {
        get(target, key, receiver) {
            targetMap[key] = activeEffect;
            return Reflect.get(target, key, receiver);
        },
        set(target, key, value, receiver) {
            Reflect.set(target, key, value, receiver);
            if (targetMap[key]) {
                targetMap[key]();
            }
        },
    }
);

function effect(fn) {
    activeEffect = fn;
    fn();
}

effect(() => {
    log.innerHTML = p.x;
});

setInterval(function () {
    ++p.x;
}, 100);

运行效果:

上述代码实现了:p.x的值不断变化,会自动运行用到了p.x的地方,log的内容会自动更新。

上面的代码并非是从Vue3源码中抽取出来,实际Vue3的代码肯定比这复杂一些。但是核心原理是一致的。代码很少也很简单,基本上不用一一说明,这里简单说下几个核心点。

  1. 基于Proxy去拦截对象属性的赋值及获取,这也是众所周知的Vue3的响应式基础;
  2. get去做依赖收集,set去做触发依赖,get建立effect和对象的关系,set去找的属性的依赖并执行
  3. 通过全局变量 activeEffect 建立对象属性和effect直接的关联,上面只用一个对象存了key,实际肯定不能这么简单的去存储依赖关系,源码中是用的 WeakMap,存储了对象、属性、effect的之前的依赖关系(如下图所示)。

转载请注明出处。本文地址: https://www.qinshenxue.com/article/vue3-reactivity.html
关注我的公众号