effect 调度

第一步

目前的 effect,当数据改变之后,会自动重新执行,如下

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>

<script type="module">
import { reactive, effect } from './reactivity.js';

let obj = { name: 'xiaoming', age: 18, flag: true };
const state = reactive(obj);

effect(() => {
console.log('runner');
app.innerHTML = state.flag ? state.name : state.age;
})

setTimeout(() => {
state.flag = false;
}, 1000);
</script>
</body>
</html>

flag 的值改变了之后,effect 中的内容会自动执行

但是也可以通过调度来实现,数据更新了之后,用户自己决定执行什么逻辑

第二步

effect.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
export function effect(fn, options?) {
// fn 是用户传进来的要执行的函数
const _effect = new ReactiveEffect(fn, () => {
_effect.run();
});

_effect.run();

// -----------------------------新增开始-----------------------------
if (options) {
// 使用用户传递的属性,覆盖掉内置的属性
Object.assign(_effect, options);
}

const runner = _effect.run.bind(_effect);
// 可以在 run 方法中获取到 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
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>

<script type="module">
import { reactive, effect } from './reactivity.js';

let obj = { name: 'xiaoming', age: 18, flag: true };
const state = reactive(obj);

const runner = effect(() => {
app.innerHTML = state.flag ? state.name : state.age;
}, {
scheduler: () => {
// 新增自己的逻辑
console.log('数据更新了,不重新渲染,走自己的逻辑');
// 执行 effect 函数,重新渲染
runner();
}
})

setTimeout(() => {
state.flag = false;
}, 1000);
</script>
</body>
</html>