03-mini-vue effect scheduler
·
实现 effect 的 scheduler 功能
-
scheduler功能
- 通过 effect 的第二个参数给定的一个 scheduler 的 fn
- effect 第一次执行的时候 还会执行 fn
- 当响应对象 set update 不会执行 fn 而是执行 scheduler
- 如果说当执行 runner 的时候,会再次执行 fn
-
实现代码
class ReactiveEffect {
private _fn: any;
// ? 可选传递参数 public 自动成为实例属性
constructor(fn, public scheduler?) { // NEW ✅
this._fn = fn
}
run() {
activeEffect = this
return this._fn()
}
}
let targetMap = new Map();
export function track(target, key) {
// targetMap { target: depsMap }
// depsMap { key: dep }
// dep 存放fn 函数
let depsMap = targetMap.get(target);
if (!depsMap) {
depsMap = new Map();
targetMap.set(target, depsMap);
}
let dep = depsMap.get(key);
if (!dep) {
dep = new Set();
depsMap.set(key, dep);
}
dep.add(activeEffect);
}
export function trigger(target, key) {
const depsMap = targetMap.get(target);
const dep = depsMap.get(key);
for (let cur of dep) {
if (cur.scheduler) {
cur.scheduler();
} else {
cur.run();
}
}
}
let activeEffect;
export function effect(fn, options: any = {}) { // NEW ✅
// fn
const scheduler = options.scheduler; // NEW ✅
const _effect = new ReactiveEffect(fn, scheduler); // NEW ✅
_effect.run();
return _effect.run.bind(_effect);
}
- 测试代码
describe("scheduler", () => {
it("function", () => {
let dummy;
let run: any;
const scheduler = jest.fn(() => {
run = runner;
});
const obj = reactive({
foo: 1,
});
const runner = effect(
() => {
dummy = obj.foo;
},
{ scheduler }
);
expect(scheduler).not.toHaveBeenCalled();
expect(dummy).toBe(1);
// should be called on first trigger
obj.foo++;
expect(scheduler).toHaveBeenCalledTimes(1);
// // should not run yet
expect(dummy).toBe(1);
run();
// // should have run
expect(dummy).toBe(2);
});
});
更多推荐
所有评论(0)