The role of key in Vue
The special
attribute of key
is mainly used in the virtual DOM
algorithm of Vue
to identify VNodes when comparing old and new
Nodes
. If key
is not used, Vue
will use an algorithm that minimizes dynamic elements and tries to modify and reuse elements of the same type in place as much as possible. Instead, use key
, it will rearrange the order of elements based on changes in key
, and remove elements that key
does not exist. In addition, child elements with the same parent element must have unique key
. Repeated key
will cause rendering errors.
Related learning recommendations: javascript video tutorial
Description
## The first is the description of the official documentation. WhenVue is updating the element list rendered using
v-for, it uses the in-place update strategy by default. If the order of the data items is changed,
Vue will not move
DOM elements to match the order of the data items, but will update each element in-place and ensure they render correctly at each index position. This default mode is efficient, but only suitable for list rendering output that does not rely on child component state or temporary
DOM state, such as form input values. To give
Vue a hint so that it can keep track of the identity of each node and thus reuse and reorder existing elements, you need to provide a unique
key attribute for each item, which is recommended whenever possible. Might provide
key attribute when using
v-for unless traversing the contents of the output
DOM is very simple or deliberately relies on the default behavior for performance gains .
key in a list loop, you need to use
key to uniquely identify each node,
diffThe algorithm can correctly identify this node, find the correct position to directly operate the node, and reuse elements as much as possible. The role of
key is mainly to efficiently update the virtual
DOM. In addition, using
index as
key is not recommended. It can only ensure that
Vue is forced to update the component when the data changes to avoid in-situ reuse. It brings side effects, but it cannot guarantee maximum element reuse, and using
index as
key has basically the same effect on data update as not using
key.
Example
First define aVue instance and render four lists, namely simple lists and complex lists. And compare the speed of updating and rendering when carrying
key and not carrying
key. This test uses
Chrome 81.0, every time in
ConsoleWhen executing code, the interface will first be refreshed and reloaded to avoid the impact of the browser and
Vue's own optimization.
<!DOCTYPE html> <html> <head> <title>Vue</title> </head> <body> <p id="app"> <ul> <li v-for="item in simpleListWithoutKey" >{{item}}</li> </ul> <ul> <li v-for="item in simpleListWithKey" :key="item" >{{item}}</li> </ul> <ul> <li v-for="item in complexListWithoutKey"> <span v-for="value in item.list" v-if="value > 5">{{value}}</span> </li> </ul> <ul> <li v-for="item in complexListWithKey" :key="item.id"> <span v-for="value in item.list" :key="value" v-if="value > 5">{{value}}</span> </li> </ul> </p> </body> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { simpleListWithoutKey: [1, 2, 3, 4, 5, 6], simpleListWithKey: [1, 2, 3, 4, 5, 6], complexListWithoutKey:[ {id: 1, list: [1, 2, 3]}, {id: 2, list: [4, 5, 6]}, {id: 3, list: [7, 8, 9]} ], complexListWithKey:[ {id: 1, list: [1, 2, 3]}, {id: 2, list: [4, 5, 6]}, {id: 3, list: [7, 8, 9]} ], } }) </script> </html>
Simple list
In the case of a simple list, not usingkey may be better than using
In the case of key, the rendering speed when updating is faster, which is what is mentioned in the official documentation, unless traversing the output
DOM content is very simple, or deliberately relying on the default behavior to gain performance improvement. In the following example, you can see that the rendering speed is faster when the list is updated without
key. When
key does not exist, the list is directly reused in place. The position of the original node remains unchanged, the elements are reused in place, and the content is updated to
5,
6,
7,
8 ,
9,
10, and two nodes
11 and
12 are added, and
key exists Next, the original
1,
2,
3,
4 nodes are deleted, and
5,
6 nodes are retained, and
7,
8,
9,
10,
11, are added.
12 Six nodes, because the addition and deletion of
DOM is time-consuming, so it is faster without
key.
// 没有key的情况下 console.time(); vm.simpleListWithoutKey = [5, 6, 7, 8, 9, 10, 11, 12]; vm.$nextTick(() => console.timeEnd()); // default: 2.193056640625ms
// 存在key的情况下 console.time(); vm.simpleListWithKey = [5, 6, 7, 8, 9, 10, 11, 12]; vm.$nextTick(() => console.timeEnd()); // default: 3.2138671875ms
DOM List rendering output of status, such as form input values.
在不设置key
的情况下,元素中没有与数据data
绑定的部分,Vue
会默认使用已经渲染的DOM
,而绑定了数据data
的部分会进行跟随数据渲染,假如操作了元素位置,则元素中未绑定data
的部分会停留在原地,而绑定了data
的部分会跟随操作进行移动,在下面的例子中首先需要将两个A
之后的输入框添加数据信息,这样就制作了一个临时状态,如果此时点击下移按钮,那么不使用key
的组中的输入框将不会跟随下移,且B
到了顶端并成为了红色,而使用key
的组中会将输入框进行下移,且A
依旧是红色跟随下移。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>就地复用</title> </head> <body> <p id="app"> <h3>采用就地复用策略(vuejs默认情况)</h3> <p v-for='(p, i) in persons'> <span>{{p.name}}<span> <input type="text"/> <button @click='down(i)' v-if='i != persons.length - 1'>下移</button> </p> <h3>不采用就地复用策略(设置key)</h3> <p v-for='(p, i) in persons' :key='p.id'> <span>{{p.name}}<span> <input type="text"/> <button @click='down(i)' v-if='i != persons.length - 1'>下移</button> </p> </p> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> <script> new Vue({ el: '#app', data: { persons: [ { id: 1, name: 'A' }, { id: 2, name: 'B' }, { id: 3, name: 'C' } ] }, mounted: function(){ // 此DOM操作将两个A的颜色设置为红色 主要是为了演示原地复用 document.querySelectorAll("h3 + p > span:first-child").forEach( v => v.style.color="red"); }, methods: { down: function(i) { if (i == this.persons.length - 1) return; var listClone = this.persons.slice(); var one = listClone[i]; listClone[i] = listClone[i + 1]; listClone[i + 1] = one; this.persons = listClone; } } }); </script> </body> </html> <!-- 源于 https://www.zhihu.com/question/61078310 @霸都丶傲天 有修改-->
复杂列表
使用key
不仅能够避免上述的原地复用的副作用,且在一些操作上可能能够提高渲染的效率,主要体现在重新排序的情况,包括在中间插入和删除节点的操作,在下面的例子中没有key
的情况下重新排序会原地复用元素,
但是由于v-if
绑定了data
所以会一并进行操作,在这个DOM
操作上比较消耗时间,而使用key
得情况则直接复用元素,v-if
控制的元素在初次渲染就已经决定,在本例中没有对其进行更新,所以不涉及v-if
的DOM
操作,所以在效率上会高一些。
console.time(); vm.complexListWithoutKey = [ {id: 3, list: [7, 8, 9]}, {id: 2, list: [4, 5, 6]}, {id: 1, list: [1, 2, 3]}, ]; vm.$nextTick(() => console.timeEnd()); vm.$nextTick(() => console.timeEnd()); // default: 4.100244140625ms
console.time(); vm.complexListWithKey = [ {id: 3, list: [7, 8, 9]}, {id: 2, list: [4, 5, 6]}, {id: 1, list: [1, 2, 3]}, ]; vm.$nextTick(() => console.timeEnd()); // default: 3.016064453125ms
The above is the detailed content of Detailed code explanation example of the role of key in Vue. For more information, please follow other related articles on the PHP Chinese website!