關於v-for的一點小總結

簡單介紹

在vue裏面,咱們經過v-for指令來渲染一個數組列表,列表項須要咱們定義一個別名,即:html

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>
複製代碼

在上面這個例子中,items是咱們要渲染的數組列表,item是數組列表項的別名,固然,咱們能夠給v-for添加第二個參數做爲當前項的索引:vue

<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ index }} - {{ item.message }}
  </li>
</ul>
複製代碼

有經驗的同窗可能會指出,上面的例子都少了一個屬性: key,是的,官方文檔建議咱們給v-for渲染的每個列表項指定一個key,那麼,key的做用是什麼呢?vue官方文檔給瞭如下的解釋:算法

當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用「就地複用」策略。若是數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序, 而是簡單複用此處每一個元素,而且確保它在特定索引下顯示已被渲染過的每一個元素。這個相似 Vue 1.x 的 track-by="$index" 。數組

這個默認的模式是高效的,可是隻適用於不依賴子組件狀態或臨時 DOM 狀態 (例如:表單輸入值) 的列表渲染輸出。bash

爲了給 Vue 一個提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,你須要爲每項提供一個惟一 key 屬性。理想的 key 值是每項都有的惟一 id。這個特殊的屬性至關於 Vue 1.x 的 track-by ,但它的工做方式相似於一個屬性,因此你須要用 v-bind 來綁定動態值 (在這裏使用簡寫):dom

<div v-for="item in items" :key="item.id">
  <!-- 內容 -->
</div>
複製代碼

建議儘量在使用 v-for 時提供 key,除非遍歷輸出的 DOM 內容很是簡單,或者是刻意依賴默認行爲以獲取性能上的提高。由於它是 Vue 識別節點的一個通用機制,key 並不與 v-for 特別關聯,key 還具備其餘用途,咱們將在後面的指南中看到其餘用途。ide

提出問題

問題1: 什麼是'就地複用'?

這裏我舉一個簡單的例子來講明一下:性能

在一個玩具組裝車間,小A, 小B, 小C,小D以及其餘96個流水線工人一塊兒完成組裝玩具的工做,每一個人都有本身的一輛玩具在組裝,忽然,小B肚子痛跑去上廁所了,可是小B的工做還沒完成,爲了避免影響總體進度,工人都依次往前補,小C頂替了小B的工做,小D頂替了小C的工做,以此類推,這樣雖然也是有點麻煩,還好工做定期完成了。ui

這就是就地複用大概的思路,若是不採用就地複用,那麼,當小B缺席以後,流水線上的工人(包括小B以前的)都要從新排序,100我的按照工號從新排序,從新獲取本身的工做內容,這樣子工做效率就大大下降了。this

在DOM中,就地複用的是那些沒有變化的元素,例如:

<div v-for="item in items">
  <input/>
  {{item.message}}
</div>
複製代碼

在這段代碼中,沒有變化的元素就是input,當咱們刪除items的某個元素時,item.message會發生變化,所以渲染的數據發生了變化,可是已經存在dom中的input卻會被就地複用,具體的演示效果以下:

問題2: 如何解決就地複用產生的問題?

正如咱們上面看到的那樣,咱們但願input也被從新渲染,這個問題的解決方案vue已經在文檔中說的很清楚了,咱們須要給每個列表項加上一個惟一的key屬性

問題3: key屬性是如何解決問題的,它的原理是什麼?

這個問題就涉及到了虛擬DOM的diff算法了,具體原理能夠查看知乎的一篇文章

問題4: 沒有添加key屬性或者key屬性不是惟一的會出現什麼坑?

key屬性須要綁定一個惟一的值,可是在咱們的實際項目中,不必定會有這麼一個惟一的值讓咱們綁定,所以習慣性咱們會採用index做爲key屬性的值,這樣作就容易產生問題了...

由於index對應的value值是會變化的,例如:

list: [
  {index: 0, value: 0},
  {index: 1, value: 1},
  {index: 2, value: 2}
]
複製代碼

當咱們執行list.splice(1, 1)移除index = 1的項時,list數組就會變成:

list: [
  {index: 0, value: 0},
  {index: 1, value: 2}
]
複製代碼

由於index是數組元素的索引,當某個元素被移除時,被移除元素後面的元素索引都會更新,也就是說index並非惟一的,因此vue就會採用 就地複用 原則,這時若是頁面上有相似於input這種跟value值沒有綁定關係的元素時,這些元素將會被複用,有可能就得不到咱們要的效果了

總結: 相信用vue的人都會遇到這麼一個列表渲染元素混亂的問題,key屬性看似簡單可是第一次遇到的時候是會很納悶的,關於列表渲染比較常見的坑還有數組和對象的監測和更新,this.$set你值得擁有,詳情能夠查看官方文檔,本文若是有錯漏,歡迎指出~

相關文章
相關標籤/搜索