Original link to my blog, welcome STAR.

First of all, do you have any friends with vscode? Recommend a magic font, since the use of this font, typing efficiency is sky high. Here’s how it looks:

Are congruent

Arrow function

Less than or equal to

There are many others, not to mention them all. Did you catch your eye? No. I’ll come back to you later.

The recommended article is from here. Reading this article will help you understand the structure of the Vue application. Although it is version 1.0, version 2.0 retains most of the 1.0 API.

In this article, I will be a summary of my study of Vue in these months.


Train of thought

Vue and other MVVM ideas are similar:

The main purpose is to achieve three processes:

  1. Observer: The Observer listens to data and provides the ability to subscribe to changes to a data item. Object. DefineProperty is used to convert every attribute in data into getter/setter, intercepting Object assignment and value operation.

  2. Compiler: Parse template into the render() method;

  3. Watcher: Compiler’s parsing results are combined with the Observer to receive notification when the Observer is listening for changes in data, which in turn triggers re-render and re-renders the DOM.


new Vue

Let’s start with New Vue,

The diagram above is a life cycle diagram provided by the official website, which mainly consists of four processes:

  • Create: Runs when new Vue() creates a Vue object.
  • Mount: Generates vNodes according to EL, template, render, etc., completes diff algorithm and mounts to DOM.
  • Updata: The DOM is re-rendered when the data changes.
  • Destory: Runs when Vue is destroyed.

Now, let’s go into the source code and analyze the implementation:

  • Create: Run firstnew vue()Will enter_init.

    The key part of the code is as follows:


BeforeCreate and Created only have initState, which is used to implement data Observer and Event /watcher.

  • In the Mount:_initFinally, it will runvm.$mountMethods:

$mount vm.$mount Finally render() is performed to give vNodes and the real DOM after DIFF algorithm.

  • Update: After DOM, the Update method is used:

      vm._watcher = new Watcher(vm, () => {
        vm._update(vm._render(), hydrating)
      }, noop)Copy the code

The above is represented by a sequence diagram:


Deep Responsive Principle (Observer, Watcher)

An important feature of the MVVM framework is that it automatically updates the corresponding DOM nodes when data changes. How is Vue implemented?

This is a picture from the official website.

As mentioned earlier, the initState() method is run between the beforeCreate and Created lifecycle hook functions.

InitState () :

In this method, properties like props, data, computed, etc., are converted to getters/setters using Object.defineProperty.

We use initData() as an example:

Proxy (vm, “_data”, keys[I]) sets vm._data as the proxy, implementing vm.a === vm._data.

Observe (data, this) at the end of initData().

In observe(), both convert to getter/setter.

  Object.defineProperty(obj, key, {
    enumerable: true.configurable: true.get: function reactiveGetter () {
      const value = getter ? getter.call(obj) : val
      Target is the getter fired by the Vue's internal dependency collection process
      // Dep.depend () to add watcher(the actual value of dep.target) to the subs array of deP
      For other times, such as in the DOM event callback function, the getter triggered by accessing this variable does not need to perform the dependency collection and simply returns the value
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          // If value generates an OB instance during Observe, make ob's DEP collect dependencies as well
          childOb.dep.depend()
        }
        if (isArray(value)) {
            // If the array element is also an object, their observe procedure also generates an OB instance
            dependArray(value)
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      var value = getter ? getter.call(obj) : val
      if (newVal === value) {
        return
      }
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      // Observe this new data
      childOb = observe(newVal)
      // Notify deP for data update.
      dep.notify()
    }
  })Copy the code

At this point, Observer listening is complete, and if the data is updated, we call dep.notify() :

Dep.notify (), update() :

The queueWatcher() method is used in update() :

QueueWatcher (), whose purpose is to execute run() via nextTicker:

In run(), we call this.get() :

In the get() method, the this.getter() method is run to update the DOM.

What is the this.getter() method?

Then there is the second argument to the new Watcher() mentioned above.

vm._watcher = new Watcher(vm, () => {
  vm._update(vm._render(), hydrating)
}, noop)Copy the code

After the new Watcher construction is complete, this.get() is called, which fires this.getter(), and the method fires DOM updates.

For details, see watcher.js:

Screenshot of a key code section:

The above, represented by a sequence diagram, is:

To sum up the above:

  • First of all,_init, the use of attributesObject.definePropertyTo convert the property togetter/setterIn thesetterMethod, will calldep.notify().
  • rightvmSet up thenew Watcher.
  • dataUpdate data when changing.

To the end.