寫 React / Vue 項目時爲什麼要在列表組件中寫 key,其作用是什麼

寫 React / Vue 項目時爲什麼要在列表組件中寫 key,其作用是什麼?

  • 沒有綁定key的情況下,並且在遍歷模板簡單的情況下,會導致虛擬新舊節點對比更快,節點也會複用。而這種複用就是就地複用,一種鴨子辨型的複用。

  <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的節點數組,我們標記身份:

 [
    '<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
  ]
❝❝

1.改變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
  ]

從以上來看,不帶有key,並且使用簡單的模板,基於這個前提下,可以更有效的複用節點,diff速度來看也是不帶key更加快速的,因爲帶key在增刪節點上有耗時。這就是vue文檔所說的默認模式。但是這個並不是key作用,而是沒有key的情況下可以對節點就地複用,提高性能。

這種模式會帶來一些隱藏的副作用,比如可能不會產生過渡效果,或者在某些節點有綁定數據(表單)狀態,會出現狀態錯位。VUE文檔也說明了 「「這個默認的模式是高效的,但是隻適用於不依賴子組件狀態或臨時 DOM 狀態 (例如:表單輸入值) 的列表渲染輸出.」」

但是KEY的作用是什麼呢?

❝❝

key是給每一個vnode的唯一id,可以依賴key,更準確,更快的拿到oldVnode中對應的vnode節點。

❞❞
  1. 更準確

    因爲帶key就不是就地複用了,在sameNode函數 a.key === b.key對比中可以避免就地複用的情況。所以會更準確。

  2. 更快

    利用key的唯一性生成map對象來獲取對應的節點,比遍歷方式更快。

本文使用 mdnice 排版

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章