effect函数
# 概述
effect
函数是 vue3 响应式系统中的核心函数,是用来创建响应式副作用的重要工具,其内部维护一个dirty
属性,该属性用来标识当前副作用是否需要重新执行。
# effect
定义
effect
定义如下:其首先检测参数fn
的effect
是否是ReactiveEffect
的实例,如果是则将effect.fn
赋值给参数fn
。然后创建一个ReactiveEffect
实例(第三个参数scheduler
内部是运行_effect.run()
),并赋值给_effect
;如果定义使用effect
时,传入了参数option
,则将其传给_effect
。如果options
或者options.lazy
为false
,则运行一次_effect.run()
。最后,定义一个runner
函数,它本质上就是_effect.run
,通过bind
函数绑定this
指向,将_effect
赋值给runner
的effect
属性,最终返回runner
。
function effect(fn, options) {
if (fn.effect instanceof ReactiveEffect) {
fn = fn.effect.fn;
}
const _effect = new ReactiveEffect(fn, shared.NOOP, () => {
if (_effect.dirty) {
_effect.run();
}
});
if (options) {
shared.extend(_effect, options);
if (options.scope) recordEffectScope(_effect, options.scope);
}
if (!options || !options.lazy) {
_effect.run();
}
const runner = _effect.run.bind(_effect);
runner.effect = _effect;
return runner;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
effect
从源码上来观察,它更像是调用ReactiveEffect
生成的实例的run
方法,
# ReactiveEffect
类的实现
ReactiveEffect
类的伪代码如下
class ReactiveEffect {
constructor(fn,trigger, scheduler, scheduler) {
this.fn = fn; // 参数fn
this.trigger = trigger; // 触发器
this.scheduler = scheduler; //调度器
this.active = true; // 是否激活
this.deps = [];// 依赖函数的集合
this._dirtyLevel = 4;// 0:不需要任何操作,当前effect是干净的 1:正在检查或查询 2:表示计算属性或副作用可能影响其值 3:类似于2 4:需要更新或者处理
this._trackId = 0;//递增
this._runnings = 0;// 运行次数
this._shouldSchedule = false;// 是否需要调度
this._depsLength = 0;// 依赖长度
recordEffectScope(this, scope);
}
get dirty(){} // 获取脏值 dirtyLevel 的取值
set dirty(){} //设置脏值 dirtyLevel 的状态 true则设为4,fals 设为0
run(){}
stop(){}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# trackEffect
依赖收集
trackEffect
的作用就是进行依赖收集,其实现如下:
function trackEffect(effect2, dep, debuggerEventExtraInfo) {
if (dep.get(effect2) !== effect2._trackId) {
dep.set(effect2, effect2._trackId);
const oldDep = effect2.deps[effect2._depsLength];
if (oldDep !== dep) {
if (oldDep) {
cleanupDepEffect(oldDep, effect2);
}
effect2.deps[effect2._depsLength++] = dep;
} else {
effect2._depsLength++;
}
if (true) {
effect2.onTrack?.(extend({ effect: effect2 }, debuggerEventExtraInfo));
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# triggerEffects
编辑 (opens new window)
上次更新: 2024/07/23, 11:04:04