iT邦幫忙

2021 iThome 鐵人賽

DAY 10
0
Modern Web

Vue.js 什麼意思系列 第 10

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 09:遍歷資料好便利-v-for
下一篇
Day 11:Router 怎麼繞-router-link、router-view
系列文
Vue.js 什麼意思30

尚未有邦友留言

立即登入留言