What is the MVVM

The model – view – the viewModel.

Model: Data model

View: The view layer

ViewModel: Can be understood as a bridge between view and model

His design idea is to pay attention to the Model changes, through the viewModel to automatically update the DOM state, which is a feature of Vue: data driven.

What does Vue do with MVVM ideas

1. Manipulate the DOM with data

We know that Vue uses a concise template syntax to render data into the DOM system. For example: {{… }} to bind data, or output HTML code using V-HTML instructions, and so on. First of all, we need to render these objects into the target content. The implementation idea is explained in detail in the Mounted section below.

2. Monitor data changes and automatically update the DOM

When we detect changes in the data, we can listen for the changes and then perform the first step of manipulating the DOM node to update the content. This involves what we call the publish and subscribe model. This is explained in the beforeUpdate section later in this article.

The realization of MVVM in Vue is discussed based on Vue life cycle

Vue official website explains the Vue life cycle:

  • beforeCreate

    Vue creates a Vue instance object, which is used to process DOM elements, and the Vue object is then accessible. Using the beforeCreate hook, we can perform some methods before the object is initialized.

    El :undefined // The virtual DOM exists and has not been mounted. Data :undefinedCopy the code
  • created

    At this stage, all data and built-in methods are initialized, but the EL is still unmounted, and data can be accessed.

    Of course, the initialization order of the built-in methods is props => methods =>data => computed => watch.

    If you have dynamic data that needs to be requested, you can initiate a request at this stage.

    Data :[object object] // InitializedCopy the code
  • beforeMouted

This step does a number of things:

First check if there is an EL object, if not, stop compiling, and the Vue instance’s life cycle ends at create.

If there are mounted DOM nodes, then look to see if any templates are used in the DOM layer.

If so, put the template in the render function (if it is a single-file component, the template will be compiled ahead of time).

If there is no template, the external HTML is compiled as a template (thus, we find that template takes precedence over the external HTML).

Of course, if we use template syntax, such as {{… }} V-html and so on, they still exist as virtual DOM and are not compiled

El :[object HTMLDivElement] // It is mounted, but the template language is not compiled // for example: <div id="app"</div> data:[object object] // Has been initializedCopy the code
  • mounted

This step is to use the Compile modules compiled template language, of course, this step because the content of the replacement, will cause a lot of re-flow and re-paint, so this step, in memory (the document. The createDocumentFragment ()).

We have a general idea for content replacement:

  1. Recursively traverses all nodes, divided into text nodes and element nodes.
    /* param all element nodes (this.el) into memory */
    node2fragment(node){
        // Create a document fragment in memory
        let fragment = document.createDocumentFragment();
        let firstChild;
        while(firstChild = node.firstChild){
            // Each element fragment is placed in memory
            // Since the node is put into memory, it can be thought of as an operation similar to an unstack operation
            // Each time a new node is fetched, until the node runs out
            fragment.appendChild(firstChild);
        }
        return fragment
    }
Copy the code
  1. For text nodes: find if {{}} exists, if so, get the expression inside {{}}, get the corresponding content of the expression, render the content

    For element nodes: we look for v- related attributes, and if so, get the instruction after v- and the corresponding value of the expression of the instruction

    /* param memory node compiles the DOM node in memory, replacing {{}} contents with data */
    compile(fragment){
        // Get the child node of the first layer
        let childNodes = fragment.childNodes;
        [...childNodes].forEach( item= >{
            if( this.isElementNode(item) ){
                // If it is an element, look for a directive similar to v-model
                this.CompileElement(item);
                // If it is an element, the child nodes of the element are recursively traversed
                this.compile(item);
            }else{
                // If it is text, see {{}}
                this.CompileText(item); }})}Copy the code

Here’s an example:

<div id="app">
    {{name}}
    <input v-model="name"/>
</div>

<script>
    let vm = new Vue({
        el:"#app",
        data(){
            return{
                name:"Amy"
            }
        }
    })
</script>
Copy the code

We iterate over the nodes, a div element, an input, four text elements: a {{name}} and three empty newlines

We then judge them, and the useful nodes are {{name}} and an input element, so we process them separately

For the text node {{}}, we want to replace it with the text “Amy”, and for the input node we want the name and value bindings.

Once compiled, our DOM tree is done rendering to the page.

// <div id="app">Amy</div> data:[object object] // Is initializedCopy the code

Complement the browser’s rendering mechanism

1. Parse HTML code to generate DOM tree 2. Parse CSS to generate CSSOM 3. Combining DOM tree and CSSOM tree to generate render tree Use depth-first traversal (diff algorithm) to traverse the render nodes. Of course, the order of CSS rendering is exactly the order of CSS writing. If CSS writing order is not standardized, this step may also cause a lot of backflow and redrawCopy the code
  • BeforeUpdate, updated

    BeforeUpdate executes before listening for data changes, the virtual DOM is re-rendered and the update is applied, and updated after the change is complete.

    The question here is how does Vue detect changes in data? How is the view layer notified of the update?

    This is the core idea of MVVM. The view-Model connects the view layer to the data Model. Vue uses what we call a publish-subscribe Model, which involves several classes.

The Observer:

Data hijacking to achieve two-way data binding. In this case, he is a publisher, publishing information about data changes.

We use the Object.defineProperty method to bind all attributes of data to get and set methods so that we can listen for every read and modification.

Dep:

Collect Watcher dependencies, one Dep for each property, to notify Watcher of data changes.

The constructor has a sub array that holds multiple Watcher, because a property can be used on multiple nodes, and each node that uses the property has a Watcher.

There are two methods: subscribe to addSub (add Watcher) and publish notify (notify Watcher).

Watcher:

The subscriber. The Compiler adds Watcher to each compiled element node and text node, triggering a Watcher callback to inform the view layer of the change once the data is updated.

  • beforeDestory

    All methods and instances are accessible at this point before the Vue is destroyed and freed from memory.

    For example, we usually clear the timer at this stage.

  • destroyed

    Vue instance memory is freed, at which point all child components, practice listeners, and watcher are cleared.

Data hijacking for Vue2.0 and Vue3.0

Vue2.0 hijacks data with Object.definepeoperty; Vue3.0 uses Proxy to Proxy data.

The biggest difference is that Object.definepeOperty can only Proxy a property of an Object, whereas Proxy can Proxy objects and arrays directly.

Little white beginner! If there are mistakes welcome to correct!