The profile

About the key question in V-for, in fact, this is a very common question, the basic Internet search, the interview is often asked, this question may design the DOM and virtual DOM, as well as the important Diff algorithm. portal

Function (the main act)

As we all know, a big feature of Vue is two-way data binding, which renders new data on the page as soon as the data changes.

The problem is that for tabular data rendered with V-for, the amount of data can be very large, and we often need to add or delete the data. Suppose we add one piece of data to the list, and the whole list has to be rendered again, which is a lot of work.

The key is designed to avoid this problem as much as possible, and improve efficiency. If we add one piece of data to the list, and the page only renders that data, it will be perfect.

By default, V-for uses the in-place reuse policy. When the list data is modified, it will judge whether a value is modified according to the key value. If it is modified, it will re-render this item; otherwise, it will reuse the previous element.

We often use index as a key, but it’s not really recommended. Such as:

list = [
    {
        id: 1,
        num: 1
    },
    {
        id: 2,
        num: 2
    },
    {
        id: 3,
        num: 3
    },
];
Copy the code

<div v-for="(item, index) in list" :key="index">{{item.num}}</div>

In this case, we used index as the key.

1. Append a piece of data to the array

List = [{id: 1, num: '1'}, {id: 2, num: 2}, {id: 3, num: 3}, {id: 4, num: 'new data 4'}].Copy the code

At this time, the first three data pages will not be rerendered, and the previous ones will be directly reused. Only the last data will be newly rendered. At this time, index is used as the key, and there is no problem.

2. Insert a data line in the middle of the array

List = [{id: 3, num: 1}, {id: 4, num: 'new data 4}, {id: 2, num:' 2 '}, {id: 3, num: '3'}].Copy the code

When the page renders the data, it compares the key defined by index with the following:

Data after the previous data key: 0 Index: 0 NUM: 1 key: 0 Index: 0 NUM: 1 key: 1 Index: 1 NUM: 2 Key: 1 Index: 1 NUM: 'New data 4' Key: 2 index: 2 num: 3 key: 2 index: 2 num: 2 key: 3 index: 3 num: 3Copy the code

Through the clear comparison above, it is found that except the first data can be reused before, the other three data need to be re-rendered.

Isn’t it surprising that I only inserted one piece of data, but why should I rerender all three pieces of data? And all I want is that new piece of data to be rendered.

The best way to do this is to use the item in the array that does not change as the key value, which corresponds to the item, that is, each piece of data has a unique ID to identify the uniqueness of that piece of data. Using id as the key value, let’s compare inserting a piece of data in the middle. How does it render? Such as:

List = [{id: 1, num: 1}, {id: 4, num: 'new data 4}, {id: 2, num: 2}, {id: 3, num: 3}].Copy the code
Data after the previous data Key: 1 ID: 1 Index: 0 NUM: 1 KEY: 1 ID: 1 Index: 0 NUM: 1 key: 2 ID: 2 Index: 1 NUM: 2 KEY: 4 ID: 4 Index: 1 NUM: 'New data 4' Key: 3 ID: 3 Index: 2 NUM: 3 key: 2 ID: 2 Index: 2 NUM: 2 KEY: 3 ID: 3 Index: 3 Num: 3Copy the code

Now it is found that only one piece of data has changed, that is, the data with ID 4. Therefore, it is ok to render this piece of data newly, and all the other data will be reused.

Similarly, when you use map to render lists in React, you must add a key, and it is recommended to use an ID, for this reason.

In fact, the real reason is not vue and React, but because the Virtual DOM uses the Diff algorithm.

aboutDiffIntroduces a

(1) When the data on the page changes, the Diff algorithm will only compare nodes of the same level. (2) If the node type is different, simply kill the previous node, create and insert a new node, and do not compare the children of this node. (3) If the nodes are of the same type, the attributes of the nodes will be reset to achieve node update.

For example

Let’s insert a piece of data into a list:

The Diff algorithm defaults to this:

In this case, the efficiency is very slow. At this time, we need to use key to make a unique identifier for each node. Then Diff algorithm can correctly identify this node and find the correct location area to insert a new node.