Appearance
调度器
本节目标:理解“调度器”的核心思路,并能把它用于实际开发或面试表达。
export class ReactiveEffect {
public deps = [];
public parent = null;
public active = true
constructor(public fn, ==public== ==scheduler==) { }
run() {
if (!this.active) {
return this.fn();
}
try {
this.parent = activeEffect;
activeEffect = this;
// 这里我们需要在执行用户函数之前将之前收集的内容清空
cleanupEffect(this)
return this.fn();
} finally {
activeEffect = this.parent;
this.parent = null;
}
}
==stop====()== =={==
==if== ==(====this====.====active====)== =={==
==this====.====active== ===== ==false====;==
==cleanupEffect====(====this====);== ==//== ==停止====effect====的收集==
==}==
==}==
}export const effect = (fn, options: any = {}) => {
const _effect = new ReactiveEffect(fn, options.scheduler);
_effect.run();
// 将实例的Run方法绑定到effect上,然后作为返回值返回
const runner = _effect.run.bind(_effect); // 绑定this执行
// 将effect挂载到runner函数上
runner.effect = _effect;
return runner
}export function trigger(target, type, key, value, oldValue) {
const depsMap = targetMap.get(target);
if (!depsMap) return; // 触发的值不在模板中使用
let effects = depsMap.get(key); // 找到了属性对应的effect
// 永远在执行之前 先拷贝一份来执行, 不要关联引用
if (effects) {
triggerEffects(effects)
}
}
export function triggerEffects(effects) {
effects = new Set(effects);
effects.forEach(effect => {
// 我们在执行effect的时候,又要执行自己,那我们需要屏蔽掉,不要无限调用
if (effect !== activeEffect) {
if (effect.scheduler) {
// 如果用户传入了调度函数,则用用户的
effect.scheduler();
} else {
effect.run() // 否则默认刷新视图
}
}
});
}export function track(target, type, key) {
if (!activeEffect) return;
let depsMap = targetMap.get(target);
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()))
}
let dep = depsMap.get(key);
if (!dep) {
depsMap.set(key, (dep = new Set()))
}
trackEffects(dep);
}export function trackEffects(dep) {
if (activeEffect) {
let shouldTrack = !dep.has(activeEffect); // 去重了
if (shouldTrack) {
dep.add(activeEffect);
// 存放的是属性对应的set
activeEffect.deps.push(dep);
}
}
}