Vue v-for指令中 key 的必要性

Vue官方文档

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute。
建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

测试样例

<template>
  <div class="for">
    <div>
      <input type="text" v-model="newUser" />
      <button @click="add">add</button>
      <ul>
        <li v-for="user of users">
          <input type="checkbox" />
          {{ user.name }}
          <button @click="remove(user.id)">remove</button>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      newUser: "",
      newId: 4,
      users: [
        {
          id: 1,
          name: "zhangsan"
        },
        {
          id: 2,
          name: "lisi"
        },
        {
          id: 3,
          name: "wangwu"
        }
      ]
    };
  },
  methods: {
    add() {
      this.users.unshift({
        id: this.newId++,
        name: this.newUser
      });
    },
    remove(id) {
      const index = this.users.findIndex(item => item.id === id);
      if (index !== -1) {
        this.users.splice(index, 1);
      }
    }
  }
};
</script>

<style scoped>
li {
  list-style: none;
}
</style>

不添加Key时

<li v-for="user of users">
  1. 选择zhangsan

  2. 添加xiaoming

  3. 发现多选框当前选中的变成了xiaoming

  4. 删除xiaoming发现当前选中的又变回了zhangsan

添加key为index时

<li v-for="(user, index) of users" :key="index">

重复上述四个步骤,发现结果与不添加key时相同。

添加key为user.id时

<li v-for="user of users" :key="user.id">
  1. 选择zhangsan

  2. 添加xiaoming

  3. 多选框当前选中的仍然是zhangsan

  4. 删除zhangsan后当前无选中节点

结论

Vue中使用key属性来标识一个dom节点,key属性值要和数据一一关联(最好是字符串或数字等基本类型),Vue通过key的值判断是否是同一个dom节点。
如果不设置key值,Vue默认使用”就地更新“策略,即只更新DOM内数据而不对DOM节点进行增减移动等操作。
如果设置的key值和数据不能对应(比如上述设置的数组index,index只与数组长度有关),也无法增减移动DOM节点。

posted @ 2020-06-15 10:32  Peterer~王勇  阅读(322)  评论(0编辑  收藏  举报