Day 10:v-for 注定绑个 key

承上篇,谈到 v-for,就要说说它的最佳良伴——key

v-for 必须绑定代表唯一值的 key

若未绑定 key 值,Terminal 会直接报错,表示「require 'v-bind:key'」,否则无法继续编辑。
require key

key 值出现重复的情况,DevTools 也会报错。
duplicate key

key 值必须是字串或数字型别

个人习惯一律准备 id 来绑定 key 值,但若是遍历的资料结构较为简单,且不会经过复杂的处理机制时,视情况可直接利用阵列的 index 作为替代。

<b-navbar-nav
  class="my_navbar_item"
  v-for="(navItem, navIndex) in navList"
  :key="navIndex"
>
  <b-nav-item href="#">{{ navItem.item }}</b-nav-item>
</b-navbar-nav>

也可以从 navList 阵列中的物件取得 item 内容来使用。

<b-navbar-nav
  class="my_navbar_item"
  v-for="navItem in navList"
  :key="navItem.item"
>
  <b-nav-item href="#">{{ navItem.item }}</b-nav-item>
</b-navbar-nav>

绑定 key 值:「id」 VS 「index

部分情况下若为求方便直接将 index 设为 key 值可能就会产生问题。

以下用一个包含 5 笔资料的简单列表 list 作为范例,并增加下拉选单一起测试看看,打开 Vue.js Devtools 观察 key 值绑定 idindex 的差别。

测试方式:先将下拉选单选定在第 4 笔资料,接着用 Vue.js Devtools 选取工具(Select)取得阵列资料後,再删除第 3 笔资料。

<div v-for="(item, index) in list" :key="index">
	index {{ index }} —— id {{ item.id }} —— {{ item.name }}
</div>
data() {
   return {
	  select: "",
      list: [
        { id: 1, name: "资料1" },
        { id: 2, name: "资料2" },
        { id: 3, name: "资料3" },
        { id: 4, name: "资料4" },
        { id: 5, name: "资料5" },
      ],
    };
},

将 <option> 的 key 值绑定 index

<p>key: select index {{ select }}</p>
<select v-model="select">
    <option v-for="(item, index) in list" :key="index" :value="index">
        {{ item.name }}
    </option>
</select>

选定第 4 笔资料,其 index 为 3。
index

删除第 3 笔资料之後,index 3 变成对应到第 5 笔资料,造成选定项目跟着变动。
index 2

改为将 <option> 的 key 值绑定 id

<p>key: select id {{ select }}</p>
<select v-model="select">
    <option v-for="item in list" :key="item.id" :value="item.id">
        {{ item.name }}
    </option>
</select>

选定第 4 笔资料,其 id 为 4。
id

删除第 3 笔资料之後,因为 id 值并未受到影响,因此选取项目仍为原本选定的第 4 笔资料。
id 2

Vue.js「就地更新(in-place patch)」

由於 Vue 采用「就地更新」策略,会以重复使用原本元件为原则来达到效能的提升,因此当资料被更新时(例如阵列资料改变排序),Vue 并不会大幅移动 DOM 元素来调整资料的顺序,而是就地更新部分被改变的资料而已,所以需要透过绑定一个可作为唯一识别的 key 值,以确保资料能被有效复用及重新排序既有的元素。

经过上述测试我们可以理出结论:

  • id 具有唯一性,能直接对应到所属项目,因此当阵列内容发生变动时,只需要处理增减的资料即可,其他资料仍可继续复用,不需要重新渲染,进而维持效能。
  • index 会跟着阵列内容的长度变化而随之增减,且 index 具有顺序性,所以只要变动其中一笔资料便会连带影响到其他资料的排序,使得资料必须随时重新渲染,相对影响效能。

参考资料


<<:  [Day 10] 前端页面路由设定 vue-router

>>:  Day_13 有线网路应用(五)

BPM懒人包 让你一次搞懂BPM的大小事

为了要了解企业流程管理(BPM),很多人上网搜寻到的文章,常常都有些八股,或是看不到想要了解的部分,...

Day18 Refs 和 DOM

React中若想将父层Component资料传递给子层Compontent的话,唯有使用Props方...

DAY 2- 编码跟加密-凯萨密码

到底念Caesar还是Caesar,我都念Caesar。 编码不等於加密 今天要厘清一个非常重要的事...

【如何快速学习新技能 ?】软技能 : 十步学习法

学习「怎样学习」 大纲 学习能力 软技能:代码之外的生存指南 十步学习法「概述」 第一部分:「研究」...

建立你想要的文化(1)

文化不是只关 CEO & 人资的事 很多人以为,「文化」是个很「高大上」的概念,就是企业决定...