对vue中的key的理解

72 阅读2分钟

key是什么

在Vue.js中,key是6个特殊属性key, ref, is, slot, slot-scope, scope其中之一。key是虚拟DOM对象的标识,具有唯一性, 主要作用于Vue的virtual DOM算法, 在使用diff算法对比新旧虚拟DOm时, 作为识别VNode(虚拟节点)的一个标识.

key在vue内部使用, vue可以高效的工作, 当把虚拟DOM渲染成真实DOM的时候,Vue就把key去掉了, key和v-for配合使用。

key的作用

01.当key值为索引的时候

先上代码:

<!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>key的原理</title>
  <script src="./js/vue.min.js"></script>
  <style>
    .cli{
      background-color: skyblue;
       margin-top: 16px;
       border-style: none;
    }
    h2{
      display: inline;
      background-color: #b0dfcb;
    }
  </style>
</head>

<body>
  <!-- 准备好一个容器 -->
  <div id="app">
    <!-- 遍历数组啦 -->
    <h2>落魄山人员列表</h2><br>
    <button class="cli" @click.once="addElement">点我添加落魄山首席弟子</button>
    <ul>
      <li v-for="(item,index) in persons" :key="index">
        {{item.name}} -- {{item.age}}
        <input type="text">
      </li>
    </ul>

    <script>
      // Vue.config.productionTip = false;
      new Vue({
        el:'#app',
        data:{
          persons:[
            {id: '1', name: '平安', age: 18},
            {id: '2', name: '宁姚', age: 19},
            {id: '3', name: '阮秀', age: 20},
          ]
        },
        methods:{
          addElement(){
            const p = {id: '4', name: '裴钱', age: 11}
            this.persons.unshift(p)
          }
        }
      })
    </script>
  </div>
</body>
</html>

看效果:

未命名-副本(3).gif

细心的小伙伴已经发现出现了错误, 让我们一起来分析下错误原因: 上分析图:

image.png

当key值为索引的时候,平安--18,宁姚--19,阮秀--20,这些文本节点没有被复用,效率低,但是呢,这个问题暴露的不是很明显,最明显的是:一旦有输入类型的节点,比如input,就可能会导致页面出现错乱。

02.当key值为id的时候

代码:

<!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>key的原理</title>
  <script src="./js/vue.min.js"></script>
  <style>
    .cli{
      background-color: skyblue;
       margin-top: 16px;
       border-style: none;
    }
    h2{
      display: inline;
      background-color: #b0dfcb;
    }
  </style>
</head>

<body>
  <!-- 准备好一个容器 -->
  <div id="app">
    <!-- 遍历数组啦 -->
    <h2>落魄山人员列表</h2><br>
    <button class="cli" @click.once="addElement">点我添加落魄山首席弟子</button>
    <ul>
      <li v-for="(item,index) in persons" :key="item.id">
        {{item.name}} --  {{item.age}}
        <input type="text">
      </li>
    </ul>

    <script>
      // Vue.config.productionTip = false;
      new Vue({
        el:'#app',
        data:{
          persons:[
            {id: '001', name: '平安', age: 18},
            {id: '002', name: '宁姚', age: 19},
            {id: '003', name: '阮秀', age: 20}
          ]
        },
        methods:{
          addElement(){
            const p = {id: '004', name: '裴钱', age: 11}
            this.persons.unshift(p)
          }
        }
      })
    </script>
  </div>
</body>
</html>

分析图: image.png 当key值为id的时候,除了key="004"的那个虚拟节点会被新生成,别的虚拟节点都被复用了,提高了效率。

03.当没有key值的时候

没有key值,也会出问题,因为你在写v-for遍历列表的时候没有写key, vue底层会做一个默认的动作,会把遍历时候的索引值自动作为key了。但是vue不会自动给你补一个数据唯一标识,因为vue不知道哪些东西是数据的唯一标识。