By learning the Vue source code parsing series (3) – reactive system depends on the collection and view updates and Vue source code parsing series (2) – response within the system how to run, our response to the Vue system have a certain understanding, and know that it is how to realize data update view, view change data, so the basis of this, Let’s write a MVVM so that we can blow the interviewer’s mind during the interview. So here’s a graph that everyone in this room is familiar with:

1, When we create a new MVVM, we have two steps, Observer,Compile, we know that Observer does data hijacking,Compile is a parsing instruction, then we have a problem:

  • ObserverWhy data hijacking?
  • CompileWhy do parse instructions?

With these two questions in mind, let’s review past content:

  • What is theData response?
  • Data responsivity principleWhat is?
  • What about data responsivenessimplementation?

Data responsiveness is two-way data binding, which binds the Model to the View. When we update the Model with JavaScript code, the View will update automatically. If the user updates the View, the Model data is automatically updated, which is called bidirectional binding.

Data responsivity principle

  • VueThe principle of data responsiveness is achieved byObject.defineProperty()This method redefines the object to get property valuesgetSetting property valuessetOperation to implement
  • Vue3.0Is throughECMAScript6In theproxyObject proxy.

This section is designed to implement data responsiveness.

So to answer the first two questions, why hijack data? Why parse instructions?

  • Only when the data is hijacked can it be listened for so that changes to the data can update the view in time.
  • VueInNMultiple instructions, only parsing it, weJavaScriptTo recognize it and run it.

We won’t repeat these questions, but let’s start with data responsiveness.

Before writing a demo, we should organize our thoughts:

1. First implement an overall architecture (including MVVM class or VUE class, Watcher class), / here use a subscription publisher design pattern. 2. Then implement MVVM from M to V to bind the data in the model to the view. 3. Finally, v-M is implemented. When the text box enters the text, the text event triggers the update of the data in the model. It also updates the corresponding view.Copy the code
/ / HTML code
<div id="app">
      <h1>MVVM bidirectional binding</h1>
      <div>
        <div v-text="myText"></div>
        <div v-text="myBox"></div>
        <input type="text" v-model="myText" />
        <input type="text" v-model="myBox" />
      </div>
</div>

Copy the code

We’ve created two divs to associate with the input box data, essentially the same data source, so where is our data source?

// Data source data
const app = new Vue({
        el: "#app".data: {
          myText: "Good luck! Chicken tonight!".myBox: "I'm a box!",}});Copy the code

We need a Vue class, that is, a publisher.

//Vue class (publisher)
class Vue{}Copy the code

With publishers, we also need subscribers:

//Watcher class (subscriber)
class Watcher{}Copy the code

So we have both, so how do we do that?

  • Get data
  • Get element object
  • Construct an object to hold the subscriber
 class Vue {
        constructor(optios) {
          this.$data = optios.data; // Get data
          this.$el = document.querySelector(optios.el); // Get the element object
          this._directive = {}; // Store subscribers}}Copy the code

So we said, we need to hijack the data, parse the instructions, so we have to construct two methods.

   class Vue {
       constructor(optios) {
         this.$data = optios.data; // Get data
         this.$el = document.querySelector(optios.el); // Get the element object
         this._directive = {}; // Store subscribers
         this.Observer(this.$data);
         this.Compile(this.$el);
       }
       // Hijacking data
       Observer(data) {
           Object.defineProperty(this.$data, key, {
             get: function(){},
             set: function(){}}}); }// View -- > Object -- > directive
       Compile(el){}}Copy the code

One is to hijack the data, the other is to parse the element instructions, the hijacked attribute to allocate the container according to the attribute, when the current container does not exist, we need to add it to the subscriber object, waiting for notification update.

  for (let key in data) {
          this._directive[key] = [];
          let val =data[key];
          let watch = this._directive[key];
  }
Copy the code

So parsing instructions, first of all, you have to recurse the current node, whether there are children, whether there are V-text instructions, V-model instructions.

 	  let nodes = el.children;
          for (let i = 0; i < nodes.length; i++) {
            let node = nodes[i];
            // Recursively query all current object subclasses to see if there are any more subclasses
            if (node.children.length) {
              this.Compile(nodes[i]);
            }
            // Check whether there is a V-text instruction
            if (node.hasAttribute("v-text")) {
              let attrVal = node.getAttribute("v-text");

              this._directive[attrVal].push(
                new Watcher(node, this."innerHTML", attrVal)
              );
            }

            // Check whether there is a V-model directive
            if (node.hasAttribute("v-model")) {
              let attrVal = node.getAttribute("v-model");

              this._directive[attrVal].push(
                new Watcher(node, this."value", attrVal)
              );
              node.addEventListener("input".() = > {
                // Assign to the model
                this.$data[attrVal] = node.value;
                // console.log(this.$data);}); }}Copy the code

So we need to collect dependencies when we trigger the update, so we just return the dependencies we collected

 Object.defineProperty(this.$data, key, {
              get: function(){
                    returnval; }}Copy the code

So what do our subscribers look like? We subscribers, receive the current element information, MVVM object, identity, attributes. And you need to construct an update method update

	class Watcher {
        constructor(el, vm, exp, attr) {
          this.el = el;
          this.vm = vm;
          this.exp = exp;
          this.attr = attr;
          this.update();
        }
        // Update the view
        update() {
          this.el[this.exp] = this.vm.$data[this.attr];
          //div.innerHTML/value = this.Vue.$data["myText/myBox"]}}Copy the code

We are almost done here, so we are going to collect the dependencies, notify Watcher to update the view, so here it is:

	Object.defineProperty(this.$data, key, {
              get: function(){
                    return val;
              },
              set: function(newVal){
                  if(newVal ! == val){ val = newVal; watch.forEach(element= >{ element.update(); }); }}});Copy the code

And when you do that, you’re ready to implement a data response.

Now that we’ve mastered the reactive principle, let’s move on to the component system, another core concept of Vue. How does $mount work