官方模拟版
2023年06月11日
一、packages/runtime-core/src/scheduler.ts
export interface SchedulerJob extends Function {
id?: number;
pre?: boolean;
active?: boolean;
computed?: boolean;
allowRecurse?: boolean;
}
export type SchedulerJobs = SchedulerJob | SchedulerJob[];
type CountMap = Map<SchedulerJob, number>;
let postFlushIndex = 0;
let isFlushPending = false;
const pendingPostFlushCbs: SchedulerJob[] = [];
let currentFlushPromise: Promise<any> | null = null;
let activePostFlushCbs: SchedulerJob[] | null = null;
const resolvePromise = Promise.resolve() as Promise<any>;
export function flushPostFlushCbs() {
if (pendingPostFlushCbs.length) {
const deduped = [...new Set(pendingPostFlushCbs)];
pendingPostFlushCbs.length = 0;
if (activePostFlushCbs) {
activePostFlushCbs.push(...deduped);
return;
}
activePostFlushCbs = [...deduped];
for (
postFlushIndex = 0;
postFlushIndex < activePostFlushCbs.length;
postFlushIndex++
) {
activePostFlushCbs[postFlushIndex]();
}
activePostFlushCbs = null;
postFlushIndex = 0;
}
}
export function flushJobs() {
isFlushPending = false;
flushPostFlushCbs();
}
export function queueFlush() {
if (!isFlushPending) {
isFlushPending = true;
currentFlushPromise = resolvePromise.then(flushJobs);
}
}
export function queuePostFlushCb(cb: SchedulerJob) {
if (Array.isArray(cb)) {
} else {
pendingPostFlushCbs.push(cb);
}
queueFlush();
}
二、测试实例
<!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>Vue3-Next-Mini Scheduler</title>
<script src="../packages/vue/dist/vue.js"></script>
</head>
<body>
<script type="module">
const { reactive, effect, queuePostFlushCb } = Vue;
const obj = reactive({
a: 1
});
effect(
() => {
console.log(obj.a);
},
{
scheduler() {
queuePostFlushCb(() => {
console.log(obj.a);
});
}
}
);
obj.a = 2;
obj.a = 3;
console.log('代码结束');
</script>
</body>
</html>