The role of key in vue

Summary

This article explains the role of the key in combination with the source code, gives a counter-example of not writing the key, and analyzes the reason.

content

  • The role of key

  • Analysis of the bugs and causes that do not write the key

  • Key practice plan

The role of key

Before and after the data change, Vue will get two virtual dom trees, and compare which nodes in the two virtual dom trees have changed in turn, so as to decide to make specific updates. There is an operation to do here: compare whether two nodes are the same node. This operation is done through sameVnode in the source code. See the code below.

 // https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.js
 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)
      )
    )
  )
 }

Assuming that we set a unique identifier for each item in a set of elements, the a.key===b.keyresults can be returned faster, which is the key to improving performance.

In practice, when rendering a set of lists, the key is often the only identifier (other conditions may be the same). Therefore, if the key is not defined, Vue can only consider the two nodes to be compared as the same (undefined===undefined ), even if they are not, this leads to frequent updating of elements, making the entire patch process relatively inefficient and affecting performance. There may even be some bugs in some special cases.

bug is coming

The following piece of code is hard-coded to illustrate the consequences if the key is not written in the v-for loop or the key is not used correctly.

 
 <div id="app" style="padding:20px">
   <coma v-for="(it,idx) in list" :i="idx" @click="d">{
  
  {it}}</coma>
 </div>
 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
 <script>
   Vue.component('coma',{
     data() {
       return {
         v: Math.random()
      }
    },
     template: `
 <div @click="$emit('click',i)">
 <slot></slot>-<span>{
  
  {v}}</span> <button>点我删除</button>
   </div>
 `,
     props: ['i']
  })
   new Vue({
     el: "#app",
     data: {
       list: [1, 2,3,4,5]
    },
     methods: {
       d(idx) {
         this.list.splice(idx, 1)
      }
    }
  })
 </script>

Bug description: When you click delete on an item, it will delete the last item instead of deleting the current item ( please focus on the last item ).

image

 

Cause Analysis

Vue describes the real dom through the virtual dom. Before updating the view, it is necessary to analyze the two virtual dom trees before and after to find their difference. If you don't set the key, Vue will use an algorithm that minimizes dynamic elements and tries to modify/reuse the same type of elements in place as much as possible. When using the key, it will rearrange the order of the elements based on the change of the key, and remove the elements whose key does not exist. See the official website https://cn.vuejs.org/v2/api/#key

 

Analyze the above bug, and click on item 2 as an example.

Expected situation, data before click:

 1,2,3

Data after click

 1,3 // The second item is deleted.

 

But since the key is not set, the changes made here are:

  1. Change the 2 in the original item 2 to 3

  2. Delete item 3.

Therefore, the serial number will be abnormal, and the last item will be deleted.

There is also a bug can be seen here https://codesandbox.io/s/vue-v-for-key-50x89. A similar situation also occurs when v-transition is used.

It is recommended to set the key

The above pits can be avoided by the following improvements:

  1. Add a unique id to the data item in the list

 data: {
    list: [{id:1,value:1},{id:2,value:3},{id:3,value:3}]
 },
  1. Modify view

 <coma v-for="(it,idx) in list" :key="it.id" :i="idx" @click="d">{
  
  {it.value}}</coma>

In this way, when deleting the second item, Vue will make the correct judgment: delete the second component.

summary

  • The key function is mainly to compare whether a node in the virtual dom is the same node more efficiently, and is used to improve the performance of the diff algorithm. To be more specific, Vue judges whether two nodes are the same node in the patch process (executing the diff algorithm, which can be translated as the patching algorithm). The same key value is a necessary condition.

  • Key will improve efficiency. In some special cases, an error will occur if the key is not written.

  • When using the v-for loop, try to avoid directly using the subscript of the array as the key, because they may cause rendering abnormalities when doing delete operations.

  • It is best to set the key as the primary key in the data item: a value that can distinguish one item from another.

Guess you like

Origin blog.csdn.net/sqLeiQ/article/details/112472865