看文章前,请先看reactive和ref的文章。
如何使用
setup() {
const refMsg2 = ref('2222')
const computed1 = computed(() => refMsg2.value+'2111111')
return () => h("div", {}, [h("p", {}, `${computed1.value}-apiInject-${refMsg2.value}`)]);
}
computed源码
- computed执行new ComputedRefImpl,我们看ComputedRefImpl
- _dirty用来标记数据是否需要更新,实现缓存作用,_dirty=true证明数据是脏的,被使用时需要重新执行一次。
- dep收集依赖
- ReactiveEffect的作用参考前几节,重点看两个参数
class ReactiveEffect {
constructor(fn, scheduler) {
this.fn = fn;
this.scheduler = scheduler;
this.active = true;
this.deps = [];
}
run() {
if (!this.active) {
return this.fn();
}
shouldTrack = true;
activeEffect = this;
const result = this.fn();
shouldTrack = false;
activeEffect = undefined;
return result;
}
...
}
- 第一个参数getter使用时传入的函数
- 第二个参数用来触发依赖
function computed(getter) {
return new ComputedRefImpl(getter);
}
class ComputedRefImpl {
constructor(getter) {
this._dirty = true;
this.dep = createDep();
this.effect = new ReactiveEffect(getter, () => {
if (this._dirty)
return;
this._dirty = true;
triggerRefValue(this);
});
}
get value() {
trackRefValue(this);
if (this._dirty) {
this._dirty = false;
this._value = this.effect.run();
}
return this._value;
}
}
当setup中使用了computed1.value
- trackRefValue依赖收集
- this._dirty是true时,则this._value = this.effect.run();run就是使用时传入的函数,同时this._dirty=false;this._dirty是false时,return this._value;
- run执行时用到了哪些响应式数据就会把compute的实例,也放进对应数据的deps中;
function triggerEffects(dep) {
for (const effect of dep) {
if (effect.scheduler) {
effect.scheduler();
}
else {
effect.run();
}
}
}
- 当computed用的数据,其中一个改变时,就会触发它所有的依赖,computed的实例是有scheduler的,执行scheduler。
- 执行scheduler就是ReactiveEffect第二个参数,computed的依赖变了则修改标记this._dirty = true,同时触发triggerRefValue(this);