例子:reactivity/dist/index.html,由用户决定何时重新渲染
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="./reactivity.global.js"></script>
<!-- <script src="../../../node_modules/@vue/reactivity/dist/reactivity.global.js"></script> -->
<script>
const { effect, reactive } = VueReactivity;
const obj = { name: 'bowen', age: 18, flag: true };
const state = reactive(obj);
const app = document.getElementById('app');
let wait = false;
let runner = effect(
() => {
app.innerHTML = state.age;
},
{
// 调度器:自行决定如何更新
scheduler() {
if (!wait) {
wait = true;
setTimeout(() => {
runner();
wait = false;
}, 1000);
}
},
}
);
state.age = 24;
state.age = 25;
state.age = 26;
</script>
</body>
</html>
effect函数增加options参数及返回值
packages/reactivity/src/effect.ts > effect
export function effect(fn, oprions: any = {}) {
// fn可以根据状态变化重新执行
// effect可以嵌套
const _effect = new ReactiveEffect(fn, oprions.scheduler);
// 默认先执行一次
_effect.run();
// 绑定this指向
const runner = _effect.run.bind(_effect);
// 将effect挂载到runner上
runner.effect = _effect;
return runner;
}
ReactiveEffect类增加调度器及stop方法
packages/reactivity/src/effect.ts > ReactiveEffect
constructor(public fn, public scheduler) {}
public stop() {
if(this.active) {
this.active = false;
cleanupEffect(this);
}
}
trigger渲染时增加调度器的判断
packages/reactivity/src/effect.ts > trigger
// 屏蔽掉相同的调用
if (effect !== activeEffect) {
if (effect.scheduler) {
// 如果传入了调度器,执行调度器
effect.scheduler();
} else {
effect.run();
}
}