第一步
计算属性维护了一个 dirty 属性,默认值是 true,运行过一次后,会将 dirty 变为 false, 并且当依赖的值变化后,会让 dirty 再次变为 true
计算属性是具备依赖收集的能力,可以收集对应的 effect,依赖的值变化后会触发 effect 重新执行
packages/reactivity/src/constants.ts
1 2 3 4 5 6 7 8
| ...
export enum DirtyLevels { Dirty = 4, NoDirty = 0 }
|
packages/reactivity/src/effect.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class ReactiveEffect { _trackId = 0; deps = []; _depsLength = 0; _running = 0; _dirtyLevel = DirtyLevels.Dirty;
public active = true;
constructor(public fn, public scheduler) { }
public get dirty() { return this._dirtyLevel === DirtyLevels.Dirty; }
public set dirty(value) { this._dirtyLevel = value ? DirtyLevels.Dirty : DirtyLevels.NoDirty; }
run() { this._dirtyLevel = DirtyLevels.NoDirty; if (!this.active) { return this.fn(); }
... } }
|
第二步
computed.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import { isFunction } from '@vue/shared'; import { ReactiveEffect } from './effect'; import { trackRefValue, triggerRefValue } from './ref';
class ComputedRefImpl { public _value; public effect; public dep;
constructor(getter, public setter) { this.effect = new ReactiveEffect(() => getter(this._value), () => { triggerRefValue(this) }); }
get value() { if (this.effect.dirty) { this._value = this.effect.run();
trackRefValue(this); } return this._value; }
set value(value) { this.setter(value); } }
export function computed(getterOrOptions) { const onlyGetter = isFunction(getterOrOptions); let getter; let setter;
if (onlyGetter) { getter = getterOrOptions; setter = () => { }; } else { getter = getterOrOptions.get; setter = getterOrOptions.set; }
return new ComputedRefImpl(getter, setter); }
|