vue3在处理effect更新时,使用事件队列,减少重复操作一个对象上的多次更新。
<script src="https://unpkg.com/vue"></script>
<div id="app"></div>
<script>
const { h, createApp, reactive } = Vue;
let App = {
setup(props, context) {
let state = reactive({ name: "aaa" });
let changeFn = () => {
state.name = "bbb";
state.name = "aaa";
state.name = "ccc";
state.name = "bbb";
};
return () => {
return h("div", { onClick: changeFn }, state.name);
};
},
};
let app = createApp(App).mount("#app");
</script>
以上代码对name进行多次更改值操作,如果没有事件调度使用,那么会进行4次更新渲染。使用调度器,把相同的任务放到一个queue中,如果事件job存在就不进行添加。
文件在runtime-core的scheduler.ts中。
// 任务队列,先去重,在依次调用
let queue = [];
export function queueJob(job) {
if (!queue.includes(job)) {
queue.push(job);
// 多个任务,只执行一次
queueFlush();
}
}
let isFlushPending = false;
function queueFlush() {
if (!isFlushPending) {
isFlushPending = true;
// 把队列中的任务,一下同时完全调用
Promise.resolve().then(flushJobs);
}
}
function flushJobs() {
isFlushPending = false;
// 按照事件的id进行排序
queue.sort((a, b) => a.id - b.id);
for (let i = 0; i < queue.length; i++) {
const job = queue[i];
job();
}
queue.length = 0;
}