1. Description of key in official documents
The special attribute of key is mainly used in Vue's virtual DOM algorithm to identify VNodes when comparing old and new nodes. If you do not use keys, Vue will use an algorithm that minimizes dynamic elements and tries to modify / reuse elements of the same type in place as much as possible.
When using a key, it rearranges the order of elements based on the change of the key, and removes elements that do not exist in the key.
Child elements with the same parent element must have a unique key. Duplicate keys can cause rendering errors.
2. Give an example 🌰
You can run the code and change the key to index idx (or do not set the key) or item.id to see the effect
- When the index idx is used as the key (or no key is set), select an item and click add new value. The selected item will change
- When item.id is used as the key, select an item. When adding, the selected item will not change
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <div> <input type="text" v-model="name"> <button @click="add">add to</button> </div> <ul> <!-- <li v-for="(item,idx) in list" :key="idx"> --> <li v-for="item in list" :key="item.id"> <input type="checkbox">ID: {} -------name: {} </li> </ul> </div> <script> var vm = new Vue({ el: '#app', data: { name: '', list: [{ id: 0, name: 'Test data 1' }, { id: 1, name: 'Test data 2' }, { id: 2, name: 'Test data 3' } ] }, methods: { add() { const newUser = { id: this.list.length, name: this.name }; this.list.unshift(newUser); } } }) </script> </body> </html>
It can be seen that when the key value is item.id, the checked item in the checkbox will not change when a new item is added. Why? Let's move on
3. diff
In vue, when the data changes, the update will be triggered. The core of the update process is the diff of the old and new vnode s.
The principle of diff is to compare the nodes in the same layer of the front and rear node trees, layer by layer, as follows
When there are many same nodes in a layer, that is, list nodes, the update process of diff algorithm also follows the above principles by default.
as follows
We hope to add an F between B and C. the default execution of diff algorithm is like this
That is, update C to F, D to C, E to D, and finally insert E, which is quite inefficient!
Therefore, we need to use the key to make a unique identification for each node. The diff algorithm can correctly identify this node, find the correct location area and insert a new node, as shown in the following figure
In vue, the sameVnode(oldVnode, vnode) function for judging the old and new nodes is as follows
function sameVnode(a, b) { return ( a.key === b.key && ((a.tag === b.tag && a.isComment === b.isComment && isDef(a.data) === isDef(b.data) && sameInputType(a, b)) || (isTrue(a.isAsyncPlaceholder) && a.asyncFactory === b.asyncFactory && isUndef(b.asyncFactory.error))) ) }
You can see that to judge whether the two nodes are the same, you first judge the key of the node
Therefore, the unique key value plays a key role when diff compares whether the old and new nodes are the same, and plays a more efficient role in updating the virtual node
4. Why not recommend index as key
You can refer to the code in the example. In the scenario of adding, deleting and changing, the index of the element may change. When diff algorithm compares the differences between the same level, it is associated with the key. When subscript transformation is performed on the array, such as deleting the first data, then all indexes will change in the future, and the key will naturally change, so index is used as the key The value is unstable, and this instability may lead to a waste of performance, so that diff cannot associate the same data as the last time. Therefore, you can not use index without using index as the key