The function and principle of key in Vue

Table of contents

introduce

The role of the key

Key value

Do not bind the key attribute

Key value is index

Key value uniquely identifies the data

Summarize


introduce

When you have used Vue, you must be very familiar with the v-for directive. This instruction is usually used to traverse array data. When using the v-for command, the key attribute must be inseparable. Do you understand this attribute and what does it do? What is the value? What is the difference? This article will introduce the function and principle of key in Vue in detail!

The role of the key

When you bind a key attribute to a list, the attribute will exist in the virtual DOM. The key is the identifier of the virtual DOM object. When the data changes, Vue will generate a new one according to the new data modified by the user. Virtual DOM. Then Vue will compare the difference between the new virtual DOM and the old virtual DOM. The comparison process can be divided into two cases:

When the same key as the new virtual DOM is found in the old virtual DOM, if the content in the virtual DOM has not changed, the previous real DOM will be used directly! If the content in the virtual DOM changes, a new real DOM is generated, and then the previous real DOM in the page is replaced.

When the same key as the new virtual DOM is not found in the old virtual DOM, a new real DOM is created and then rendered to the page.

Are you a little confused, don't worry, there will be detailed examples in the following examples! !

Key value

The key mainly has the following three situations. Now let’s take a small case to use the following methods respectively to see what the specific effects are and what the differences are.

We render a list of people on the page and add a button. When the button is clicked, a new member will be added before the list of people. (Why should it be before the list, this is a key point!)

Do not bind the key attribute

When we didn't add the key attribute when we wrote v-for, it didn't affect the effect we wanted. The corresponding implementation code and effect diagram are as follows:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>key的原理</title>
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h2>人员列表</h2>
            <button @click.once="add">添加一个老刘</button>
            <ul>
                <li v-for="p of persons">
                    {
   
   {p.name}}-{
   
   {p.age}}
                </li>
            </ul>
        </div>
​
        <script type="text/javascript">
            new Vue({
                el:'#root',
                data:{
                    persons:[
                        {id:'001',name:'张三',age:18},
                        {id:'002',name:'李四',age:19},
                        {id:'003',name:'王五',age:20}
                    ]
                },
                methods: {
                    add(){
                        const p = {id:'004',name:'老刘',age:40}
                        this.persons.unshift(p)
                    }
                },
            })
        </script>
</html>

At this time, some students may ask, can the desired effect be displayed normally without writing the key attribute? So why is it so troublesome, add an extra key attribute! In fact, when you do not add the key attribute, the system will default the value of the bound key attribute to index. The index of the list, for example: {id:'001',name:'Zhang San',age:18}'s index value is 0, {id:'002',name:'Li Si',age:19 }'s index value is 1, and so on. To identify each li tag.

Key value is index

When we add the key attribute and point the value of the attribute to index, the specific effect it achieves is the same as the above without adding the key attribute. But the specific implementation code is a little different:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>key的原理</title>
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h2>人员列表</h2>
            <button @click.once="add">添加一个老刘</button>
            <ul>
                <!-- 绑定了key属性,并将其值指向于index -->
                <li v-for="(p,index) of persons" :key="index">
                    {
   
   {p.name}}-{
   
   {p.age}}
                </li>
            </ul>
        </div>
​
        <script type="text/javascript">
            Vue.config.productionTip = false
            new Vue({
                el:'#root',
                data:{
                    persons:[
                        {id:'001',name:'张三',age:18},
                        {id:'002',name:'李四',age:19},
                        {id:'003',name:'王五',age:20}
                    ]
                },
                methods: {
                    add(){
                        const p = {id:'004',name:'老刘',age:40}
                        this.persons.unshift(p)
                    }
                },
            })
        </script>
</html>

The corresponding implementation is the same as above, and the effect can be displayed correctly. This type of writing is also relatively common. This didn't show any problem. But if I add an input box after each list now, what will happen?

 <div id="root">
            <h2>人员列表</h2>
            <button @click.once="add">添加一个老刘</button>
            <ul>
                <!-- 绑定了key属性,并将其值指向于index -->
                <li v-for="(p,index) of persons" :key="index">
                    {
   
   {p.name}}-{
   
   {p.age}}
                    <!-- 增加了input输入框 -->
                    <input type="text">
                </li>
            </ul>
        </div>

From the above renderings, we can clearly see the problem, but when there is no content in the input box, there is no problem after adding it. But when we enter the corresponding content into the corresponding input box before adding, we will find that there is a problem after adding. So why is there such a problem? Let's take a look at the following graphical demonstration:

When we use index as the key, the virtual DOM will be generated according to the data after the initial data, and the key values ​​in the corresponding li tags are 0, 1, and 2 respectively. After the data generates the initial virtual DOM, a new real DOM is created and then rendered to the page.

And when we add another piece of data, a new virtual DOM will be generated based on our new data. The new virtual DOM will be compared with the original, that is, the old virtual DOM. First find the li corresponding to the same key value. If the content in the virtual DOM has not changed, use the previous real DOM directly. If the content in the virtual DOM has changed , a new real DOM is generated, and the content in key="0" has changed from "Zhang San-18" to "Old Liu-30", and then the previous real DOM in the page is replaced. And the <input type="text"> comparison result is the same, so save the original content. key="1" and key="2" and so on. And key="3" is not found in the old virtual DOM, so a new real DOM is created and then rendered to the page.

Now I understand! !

Key value uniquely identifies the data

When we assign the value of the key attribute as the unique identifier in the data, what will happen? We assign the id value in persons to the key attribute. The specific code is as follows:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>key的原理</title>
        <script type="text/javascript" src="../js/vue.js"></script>
    </head>
    <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h2>人员列表</h2>
            <button @click.once="add">添加一个老刘</button>
            <ul>
                <!-- 绑定了key属性,并将其值指向于p.id -->
                <li v-for="(p,index) of persons" :key="p.id">
                    {
   
   {p.name}}-{
   
   {p.age}}
                    <!-- 增加了input输入框 -->
                    <input type="text">
                </li>
            </ul>
        </div>
​
        <script type="text/javascript">
            new Vue({
                el:'#root',
                data:{
                    persons:[
                        {id:'001',name:'张三',age:18},
                        {id:'002',name:'李四',age:19},
                        {id:'003',name:'王五',age:20}
                    ]
                },
                methods: {
                    add(){
                        const p = {id:'004',name:'老刘',age:40}
                        this.persons.unshift(p)
                    }
                },
            })
        </script>
</html>

 We can clearly see that if the value bound to our key attribute is the unique identifier in the data, we can get the result we want. The corresponding schematic diagram is as follows:

Since the value bound in each li tag is id, when a new member is added, its corresponding id="004", the corresponding key value is 004, which is not found in the old virtual DOM, so it is added to In the real DOM and rendered on the page. I won't explain much about the others, the principles are the same.

Summarize

If you use index as the key, you need to consider downloading two issues:

First, if the data is added in reverse order, deleted in reverse order, etc. to destroy the order , unnecessary real DOM updates will be generated. Although the interface effect is fine, the efficiency is low . Second, if the structure also contains the DOM of the input class , an incorrect DOM update will occur, and the interface will cause problems.

So how do we choose the key during the development process?

First of all, it is best to use the unique identifier of each piece of data as the key, such as id, mobile phone number, ID number, student number and other unique values. If there are no operations that destroy the order of data such as adding in reverse order or deleting in reverse order, it is only used to render the list for display, and there is no problem with using index as the key.

Guess you like

Origin blog.csdn.net/weixin_51735748/article/details/132155815