前言:在Vue中,当你用到for循环时经常会忽略添加key, 当Vue.js用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。那假如不适用key又会有什么问题呢?下面我将用一个小例子来解释加key和不加key的区别,但是我要声明一下我这里不打算解释什么DOM diff 算法,因为解释来解释去只会将问题复杂化不如一个活生生的例子来的简单明了。废话不多说了直接上代码吧。
完整代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id ="app">
    <Child v-for="(item,i) in array" :text="item" @delete="remove(i)"/>
  </div>
  <template id="child">
    <div>
      {{text}}
      <input v-model="message">
      <button @click="onDelete">delete</button>
    </div>
  </template>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app =new Vue({
      el:"#app",
      data:{
        array: [1,2,3]
      },
      methods: {
        remove(i) {
          this.array.splice(i, 1);
        }
      },
      components:{
        child:{
          template:"#child",
          props: ["text"],
          data(){
            return {
              message: "",
            }
          },
          methods: {
            onDelete() {
              this.$emit("delete");
            }
          }
        }
      }

    })
  </script>
</body>
</html>

1.不添加key

这里是三个子组件,依次在三个输入框里输入张三、李四、王五,当点击中间的那个删除按钮时,结果如下所示:

令人百思不得其解的是第三项的 王五 消失了,李四,却被保留下来了。

1.1 原因

原因在于Vue进行了如下操作,

  1. 把2换成了3,
  2. 把3删掉了,

对比前后两个数组:[1,2,3] 和 [1,3]
首先是1和1,1没变,其次2和3,发现2变成了3,最后对比undefined和3,发现3被删除了。
所以计算机得出的结论是:2变成了3以及3被删除了,有毛病吗?没毛病。

  1. 既然1没变,那么就地复用之前的1和张三就可以了,
  2. 既然2变成了3,那么李四左边的2,当然要改成3,里面的正方形就地复用。(正方形没有被删除)。因为你只是把 2 变成 3 而已,Vue 凭什么要修改其他地方?
  3. 既然「3 被删除了」,之前的「圆形」当然应该被删掉,里面的子元素也要删除。

所以现在看这个结果,是不是很合理:

1.2 解决办法

怎么让 Vue 知道我删除的是第二个,不是第三个?
这里用id作为key即可解决

现在删除第二个:

评 论