寫 React / Vue 項目時,數據列表中的key,用數組下標還是唯一值id或不寫呢?

React與Vue原理一致,以Vue爲列進行介紹


key不寫與key使用數組下標的區別

key不寫與使用數組下標作用一致。都是採默認使用“就地更新”的側臉。但不寫key會報警告。當 Vue 正在更新使用 v-for 渲染的元素列表時,它默認使用“就地更新”的策略。如果數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序,而是就地更新每個元素,並且確保它們在每個索引位置正確渲染。這個默認的模式是高效的,但是隻適用於不依賴子組件狀態或臨時 DOM 狀態 (例如:表單輸入值) 的列表渲染輸出。

如何正確使用index和id

以下爲簡單的例子:

<div id="app">
    <div v-for="i in dataList">{{ i }}</div>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    dataList: [1, 2, 3, 4, 5]
  }
})

以上的例子,v-for的內容會生成以下的dom節點數組,我們給每一個節點標記一個身份id:

  [
    '<div>1</div>', // id: A
    '<div>2</div>', // id:  B
    '<div>3</div>', // id:  C
    '<div>4</div>', // id:  D
    '<div>5</div>'  // id:  E
  ]

改變dataList數據,進行數據位置替換,對比改變後的數據
vm.dataList = [4, 1, 3, 5, 2] // 數據位置替換

// 沒有key的情況, 節點位置不變,但是節點innerText內容更新了

 [
   '<div>4</div>', // id: A
   '<div>1</div>', // id:  B
   '<div>3</div>', // id:  C
   '<div>5</div>', // id:  D
   '<div>2</div>'  // id:  E
 ]

 // 有key的情況,dom節點位置進行了交換,但是內容沒有更新
 // <div v-for="i in dataList" :key='i'>{{ i }}</div>
 [
   '<div>4</div>', // id: D
   '<div>1</div>', // id:  A
   '<div>3</div>', // id:  C
   '<div>5</div>', // id:  E
   '<div>2</div>'  // id:  B
 ]

增刪dataList列表項

  vm.dataList = [3, 4, 5, 6, 7] // 數據進行增刪

  // 1. 沒有key的情況, 節點位置不變,內容也更新了
  [
    '<div>3</div>', // id: A
    '<div>4</div>', // id:  B
    '<div>5</div>', // id:  C
    '<div>6</div>', // id:  D
    '<div>7</div>'  // id:  E
  ]

  // 2. 有key的情況, 節點刪除了 A, B 節點,新增了 F, G 節點
  // <div v-for="i in dataList" :key='i'>{{ i }}</div>
  [
    '<div>3</div>', // id: C
    '<div>4</div>', // id:  D
    '<div>5</div>', // id:  E
    '<div>6</div>', // id:  F
    '<div>7</div>'  // id:  G
  ]

性能對比

使用index作爲key

<li v-for="(item,index) in list" :key="index" >{{ item.text }}</li>

這裏是引用
使用id作爲key

<li v-for="item in list" :key="item.id">{{ n.text }}</li>

這裏是引用

性能對比小結

使用數組下標作爲key,就地複用,減少dom的刪除和修改,性能更好,

so

從以上來看,不帶有key,並且使用簡單的模板,基於這個前提下,可以更有效的複用節點,diff速度來看也是不帶key更加快速的,因爲帶key在增刪節點上有耗時。這就是vue文檔所說的默認模式。但是這個並不是key作用,而是沒有key的情況下可以對節點就地複用,提高性能。
這種模式會帶來一些隱藏的副作用,比如可能不會產生過渡效果,或者在某些節點有綁定數據(表單)狀態,會出現狀態錯位。VUE文檔也說明了 這個默認的模式是高效的,但是隻適用於不依賴子組件狀態或臨時 DOM 狀態 (例如:表單輸入值) 的列表渲染輸

舉個例子

// 使用數組下標性能更快
<div id="app">
    <div v-for="(item,i) in dataList" :key="i">{{ item.name }}</div>
</div>

// 使用id唯一值才能使xxxComponent 組件更新
<div id="app">
    <div v-for="(item,i) in dataList" :key="item.id"><xxxComponent></xxxComponent></div>
</div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章