Why should Vue be designed as asynchronous queue rendering

Time:2022-1-8

Asynchronous queue rendering

The last article was in vue2 0 through object The responsive principle of defineproperty to intercept and monitor data changes. This article will continue to explore deeply along the map. After the dependency is notified of changes, it will trigger the asynchronous rendering queue in Vue. Here we want to study the following points:

  1. Why is it designed as an asynchronous rendering queue
  2. How is rendering implemented
  3. Nexttick generated due to asynchronous rendering queue, and understand the usage scenario of nexttick

Why should Vue be designed as asynchronous queue rendering

Make a modification to the last code to increase the variables that the template depends on, as shown below

let x = ref(1);
  let y = ref(1);
  let z = ref(1);

  onXChanged(() => {
    console.log(`x: ${x.value}, y: ${y.value}, z: ${z.value}`);
  });

  x.value = 2;
  y.value = 3;
  z.value = 4;

The results printed on the console are as follows:

Why should Vue be designed as asynchronous queue rendering

We can see that the changes of X, y and Z have been performed once respectively, and these data exist in the template, so we will think that the template has been rendered three times. In the actual project, multiple rendering will incur a lot of overhead. Therefore, from the above example, we find that when there are many variable dependencies in the template, each variable modification will lead to a rendering. Can we optimize it?

We can consider the following scenarios encountered in actual work:

At ordinary times, when we work, if every once in a while, maybe 5min or 10min, there will be a plan to put forward requirements to you, or a new employee to ask you questions, or a tester to put forward bugs to you. If this frequency is very high, I believe it will take up your normal coding time, It makes you more unable to focus on completing your own work, so we may generally choose to put aside what they want to do first, let them wait, and make an appointment with themselves for a time, maybe 45 minutes or an hour. Then we can focus more on your own work during this time, and then deal with other things.

In fact, the logic of asynchronous update queue in Vue is similar. When we include dependencies on multiple variables in a function block, we can put these dependencies into a queue. After the current function is updated once, we can perform batch rendering. The following is the specific implementation code

(function () {
  // let f = n => n * 100 + 200;
  let active;

  let watch = function (cb) {
    active = cb;
    active();
    active = null;
  }
  //You need a queue to store tasks
  let queue = [];
  //Execute the tasks in the queue through micro tasks
  let nextTick = cb => Promise.resolve().then(cb);
  //Add task to queue
  let queueJob = job => {
    if (!queue.includes(job)) {
      queue.push(job)
      nextTick(flushJobs)
    }
  }

  //Perform tasks in the queue
  let flushJobs = () => {
    let job;
    while ((job = queue.shift()) !== undefined) {
      job()
    }
  }


  //Collect more dependencies
  class Dep {
    //Dependency collection, adding response dependency to DEPs
    constructor() {
      this.deps = new Set();
    }

    depend() {
      if (active) {
        this.deps.add(active)
      }
    }
    //Notification dependency update
    notify() {
      //Add task to queue
      this.deps.forEach(dep => queueJob(dep))
    }
  }

  let ref = initValue => {
    let value = initValue;
    let dep = new Dep();

    return Object.defineProperty({}, "value", {
      get() {
        dep.depend();
        return value;
      },
      set(newValue) {
        value = newValue;
        dep.notify()
      }
    })
  }

  let x = ref(1);
  let y = ref(1);
  let z = ref(1);

  watch(() => {
    console.log(`x: ${x.value}, y: ${y.value}, z: ${z.value}`);
  });

  x.value = 2;
  y.value = 3;
  z.value = 4;
})()

The test results are as follows:

Why should Vue be designed as asynchronous queue rendering

In this way, we can make the template render again after all dependencies are updated

The above nexttick returns a promise. It should be noted that the delayed callback is executed after the next DOM update cycle ends.

There are two scenarios in Vue:

  1. Vue.nextTick([callback,context])
  2. vm.$nextTick([callback])
  • Delay the callback until after the next DOM update cycle.
  • It is usually used to use this method after modifying the data to get the updated DOM in the callback
  • The method in the instance will automatically bind this of the callback to the instance
  • The code directly executed by mounted and updated in the life cycle hook function does not guarantee that the sub components are completely mounted or updated. We can use this$ Nexttick (function () {}) performs some operations after the whole view is rendered. This process is reliable.

summary

This article mainly studies Vue asynchronous rendering queue. We can see that it is mainly for the optimization of template performance, so the concept of asynchronous rendering queue is generated, which also produces Vue According to nexttick’s API, we can handle the logic after the template is more centered or the sub components are more I performance.
 

Disclaimers

This article is only learning some notes in Vue asynchronous rendering. The materials in this article will also involve references. The specific source is unknown. Please reprint them carefully for commercial purposes.