Mind mapping

preface

In the last section, we implemented the process that the page would automatically trigger the update when we changed the attribute value. In this section, we need to consider that we can avoid rendering multiple times when we modify the same attribute for many times, so we adopted the process of asynchronously updating the page internally.

The body of the

For example,

var vm = new Vue({
  el: '#app'.data: {
    name: 'Ming'.age: 20
  }
})

vm.name = 'morning'
vm.name = 'morning 1'
vm.name = 'morning 2'
vm.name = 'morning 3'
Copy the code

watcher.js

update() {
    // Will be updated several times
    this.get()
}
Copy the code

We can see that the function to re-render the page has been executed four times,vueIn order to consider the performance of the page at the time of implementation, it has done some internal optimization. Let’s take a look.

Batch asynchronous rendering

watcher.js

class Watcher {
 / /...
  update() {
    // Will be updated several times
    queueWatcher(this)}run() {
    console.log('update')
    this.get()
  }
}
Copy the code

+scheduler.js

import { nextTick } from ".. /utils"

let queue = []  // Store the watcher to update
let has = {}    // Check for duplicate watcher
let pending = false

function flushSchedulerQueue() {
  queue.forEach(watcher= > watcher.run())
  queue = []
  has = {}
  pending = false
}

export function queueWatcher(watcher) {
  let id = watcher.id
  if (has[id] === undefined) {
    has[id] = true
    queue.push(watcher)
    if(! pending) { nextTick(flushSchedulerQueue) pending =true}}}Copy the code

$nextTick

init.js

Vue.prototype.$nextTick = nextTick
Copy the code

Vm.$nextTink with asynchronous updates in a microtask

util.js

// We used to start a promise microtask for each asynchronous update. Now we need to optimize for multiple asynchronous updates to start only one microtask
let callbacks = []
let waiting = false

// The synchronization code is executed only after it is completed.
function flushCallbacks() {
  callbacks.forEach(fn= > fn())
  callbacks = []
  waiting = false
}

export function nextTick(fn) {
  callbacks.push(fn)
  if(! waiting) {Promise.resolve().then(flushCallbacks)
    waiting = true}}// nextTick() is a promise then()
Copy the code

summary

This section mainly deals with the asynchronous update after the object property changes, and the next section mainly writes the dependency collection of arrays.

Links to a series of articles (constantly updated…)

Vue source exploration (a) responsive principle

Vue source exploration (two) template compilation

A preliminary study of Vue source code (3) Single component mount (rendering)

Vue source exploration (four) dependent (object) collection process

Object asynchronous update nextTick()