1. 创建computed
    我们知道,computed可以传入两个参数作为computed值的getter和setter, 也可以传入一个getter函数, 此时vue会自动生成一个warn函数来作为创建computed的setter

  2. ComputedRefImpl类
    我们使用computed时, 会使用传入的getter和setter创建一个ComputedRefImpl的实例对象, 这个实例对象缓存computed的值,并作为target被响应式系统进行依赖收集,实际上在项目中依赖computed的订阅者依赖的都是ComputedRefImpl对象的实例

  3. computed是如何实现懒加载的?

    class ComputedRefImpl {
        constructor(getter, _setter, isReadonly) {
            this._setter = _setter;
            this._dirty = true;
            this.__v_isRef = true;
            this.effect = effect(getter, {
                lazy: true,
                scheduler: () => {
                    if (!this._dirty) {
                        this._dirty = true;
                        trigger(toRaw(this), "set" /* SET */, 'value');
                    }
                }
            });
            this["__v_isReadonly" /* IS_READONLY */] = isReadonly;
        }
        get value() {
            // the computed ref may get wrapped by other proxies e.g. readonly() #3376
            const self = toRaw(this);
            if (self._dirty) {
                self._value = this.effect();
                self._dirty = false;
            }
            track(self, "get" /* GET */, 'value');
            return self._value;
        }
        set value(newValue) {
            this._setter(newValue);
        }
    }
    
    
    
    

上面为ComputedRefImpl 源代码, 在创建一个ComputedRefImpl的时候,实例对象中会有一个_dirty 用于表示是否需要计算computed,还会绑定一个effect用于在computed依赖变动时调用

  1. effect()会创建一个computed的依赖的订阅者, 返回一个执行函数, 第一个参数为传入的函数用于执行更新, 第二个参数为options,lazy为延迟执行,(在依赖收集中,effect传入的函数会立即执行一次来完成依赖收集),computed的lazy为true不会立即执行

  2. 当computed的订阅者触发实例getter的时候,执行effect返回的函数, 得到computed的值,触发computed的依赖收集,_dirty设置为false,并缓存在ComputedRefImpl实例中。如果依赖项发生改变,就会调用effect把_dirty属性设置为true,并触发ComputedRefImpl的订阅者,触发getter,完成新的计算

Logo

前往低代码交流专区

更多推荐