vue3在处理effect更新时,使用事件队列,减少重复操作一个对象上的多次更新。

    1. <script src="https://unpkg.com/vue"></script>
    2. <div id="app"></div>
    3. <script>
    4. const { h, createApp, reactive } = Vue;
    5. let App = {
    6. setup(props, context) {
    7. let state = reactive({ name: "aaa" });
    8. let changeFn = () => {
    9. state.name = "bbb";
    10. state.name = "aaa";
    11. state.name = "ccc";
    12. state.name = "bbb";
    13. };
    14. return () => {
    15. return h("div", { onClick: changeFn }, state.name);
    16. };
    17. },
    18. };
    19. let app = createApp(App).mount("#app");
    20. </script>

    以上代码对name进行多次更改值操作,如果没有事件调度使用,那么会进行4次更新渲染。使用调度器,把相同的任务放到一个queue中,如果事件job存在就不进行添加。
    文件在runtime-core的scheduler.ts中。

    1. // 任务队列,先去重,在依次调用
    2. let queue = [];
    3. export function queueJob(job) {
    4. if (!queue.includes(job)) {
    5. queue.push(job);
    6. // 多个任务,只执行一次
    7. queueFlush();
    8. }
    9. }
    10. let isFlushPending = false;
    11. function queueFlush() {
    12. if (!isFlushPending) {
    13. isFlushPending = true;
    14. // 把队列中的任务,一下同时完全调用
    15. Promise.resolve().then(flushJobs);
    16. }
    17. }
    18. function flushJobs() {
    19. isFlushPending = false;
    20. // 按照事件的id进行排序
    21. queue.sort((a, b) => a.id - b.id);
    22. for (let i = 0; i < queue.length; i++) {
    23. const job = queue[i];
    24. job();
    25. }
    26. queue.length = 0;
    27. }