Vue from virtual DOM to data monitoring principle (Vue advanced must, recommended collection!)

Problems caused by conditional rendering (v-for) special attribute key

key attribute (equivalent to ID card)


elicit questions

We render some data in the page. There is a text box after each line of data, and then add a button. When you click, a piece of data will be added to the page

The code is as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>list</h2>
    <button @click="add">Add data</button>
    <li v-for="(p,index) in persons" :key="index">
         full name:{{p.name}} Age:{{p.age}}
        <input type="text">
    </li>

</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script type="text/javascript">
    const vm=new Vue({
        el:"#app",
        data:{
            persons:[
                {id:'1',name:'Zhang San',age:18},
                {id:'2',name:'Li Si',age:18},
                {id:'3',name:'Wang Wu',age:18}
            ]
        },
        methods:{
            add(){
                const p = {id:'4',name:'Zhao Liu',age:19}
                this.persons.unshift(p)
            }
        }
    })


</script>
</body>
</html>

Problem description

We write the previous corresponding data in the input box behind each data

Then we click add data, and we will find that there is a problem with the data just filled in, which does not correspond to the previous data (one bit in the data string)

Why does this happen?
Because we take index as the value of the key attribute
If you change the attribute value of the key to p.id, this will not happen:

 <li v-for="(p,index) in persons" :key="p.id">
         full name:{{p.name}} Age:{{p.age}}
        <input type="text">
    </li>


Let's analyze the related principles

Comparison algorithm of virtual DOM

Let's take index as an example

Above picture analysis
From left to right, from top to bottom

  1. The initial data is written in the data, and then vue will convert the initial data into the corresponding virtual DOM (with key attribute), and then generate the corresponding real DOM (without key attribute) according to the virtual DOM, and then the user operates the input box to write the data. Special attention: the user operates the content of the real DOM, not the content of the virtual dom. This corresponds to the left side of the figure above when we do not add data.
  2. When we click the button to add data, because we take index as the key value, the newly added data is in the first row, and index is 0. At this time, vue will regenerate the virtual DOM according to the new data, and then carry out the virtual DOM comparison algorithm. First, compare the data in the first row, and the key of the data in the first row is 0, Then go to the initialized virtual DOM on the left to find the data with the same key of 0. After finding the data, start to compare the data (comparing the content of the virtual DOM). First, it is found that the data of Zhang san-18 does not match the data of Lao liu-30, so the content of the initialized DOM (real DOM) cannot be reused. Then, the data of Lao liu-30 is generated by the virtual dom of the new data, Then continue to compare the virtual Dom and find that the < input type = "text" > is the same, and directly reuse the input tag in the initialized real DOM to the real dom of the new data (including the information entered by the user), so there is a problem of wrong line after adding data
  3. ...
  4. When the key is 3 in the last row of data, it is found that there is no data with key 3 in the initialized virtual DOM when comparing the virtual dom. The new virtual dom of the last row of data is directly changed into a real dom

When id is the key value


The principle is the same as the above. First find the same value of the key, and then compare it. When it is found that it is the same, directly reuse the original real DOM, and generate a new real DOM if the data is different
Brief summary:

  • The key attribute will not be displayed on the page and will be used in virtual DOM comparison
  • The contrast is the virtual DOM
  • The reused is the real DOM, while the user operates the real DOM (for example, the operation of inputting text into the text box is the real DOM, not the virtual DOM), which does not affect the virtual dom
  • If no key is written, index is used as the key by default
  • If it is not reused, the efficiency will be reduced

key principle text summary

vue monitoring data principle

Phenomenon:
When we change the data in the vue object, the page will immediately display the new data. Why?

General summary:
Attribute changes - > call the relevant attribute setter method - > re parse the template - > form a new virtual DOM - > compare the old and new pages - > generate a new page

Principle of monitoring:
Listening depends on setter and gettet

History of data in Vue object

The data in data is processed (add set, get and other methods) before entering the Vue object_ Data, and then through the data proxy to the vm, so we use Vue object. Attribute or Vue object_ Data. Attribute names can operate on the attributes in data. Due to data broker vm object_ The data. Attribute can be written as a Vue object. Attribute.

One question

After we directly operate the data in data, we will find that new data (responsive) will be displayed on the page immediately. When we directly operate the elements of the array in data, the page will not be refreshed immediately (non responsive). What is the reason?

When monitoring object properties

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <li v-for="h in hobby">
        {{h}}
    </li>

</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script type="text/javascript">
    const vm=new Vue({
        el:"#app",
        data:{
            name:"Zhang San",
            age:"18",
            hobby:["ball","run","walk"]
        }
    })


</script>
</body>
</html>

For example, name, age, and then we open it in the chrome browser and operate it on the console

We can see from the figure that the attributes of data have been added to the instance


Relevant properties have corresponding get and set methods (responsive)


The elements in the array do not add set and get methods (non responsive)

Special note: nested objects are still responsive! There are set and get methods

How to perform responsive operations on elements (non objects) in an array?

Array update detection
Change method:

Responsive operation can be achieved through the above operations

Text summary of monitoring data

Special attention:

When using vue object name. Property =... To add a property, the property has no set and get methods and has no response
code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <li v-for="h in hobby">
        {{h}}
    </li>

</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script type="text/javascript">
    const vm=new Vue({
        el:"#app",
        data:{
            name:"Zhang San",
            age:"18",
            hobby:{
                name:"Zhang San"
            }
        }
    })


</script>
</body>
</html>

We manually add the sex attribute in the console

How to solve it?

  • Vue.set()
  • vm(Vue instance name). $set() / / same usage as Vue.set()

Vue.set( target, propertyName/index, value )
Parameters:

{Object | Array} target
{string | number} propertyName/index
{any} value
Return value: the value set.

Usage:

Add a property to the responsive object and ensure that the new property is also responsive and triggers the view update. It must be used to add a new property to a responsive object because Vue cannot detect ordinary new properties (such as this.myObject.newProperty = 'hi')

Note that the object cannot be a Vue instance or the root data object of a Vue instance.

Usage example: (code or just code)

Error prone point

Vue.set() and vm.set() cannot add attributes to vm or vm's root data object (vm._data)!!!

If there is any error, please point it out!

Tags: Javascript Vue Vue.js

Posted on Sun, 26 Sep 2021 02:40:38 -0400 by Anxious