list vue 刪除後頁面渲染_43. Vue 中繫結 key 屬性的作用是什麼
技術標籤:list vue 刪除後頁面渲染
在解釋繫結 key 值的作用前,我們先來看一個示例:
<div id="app"> <key-test v-for="(item, index) in list"> <button @click="remove(index)">刪除{{item}}button> key-test> <button @click="add">新增button>div><script> Vue.component('key-test', { template: ', data: function () { return { value: Date.now() } } }) new Vue({ el: '#app', data: { list: [], index: 1 }, methods: { add: function () { this.list.push(this.index++) }, remove: function (index) { this.list.splice(index, 1) } } })script>
執行效果如下:
從執行效果中可以看到,當點選第一行刪除按鈕時,第一行的文字框內容並沒有被刪除,而是將最後一行中的文字框內容刪除了,為什麼會是這種情況呢?
這是因為用 v-for
更新已渲染過的元素列表時,它預設使用“就地複用”的策略,如果資料項的順序發生了改變,Vue
不會移動 DOM
元素來匹配資料項的順序,而是簡單複用此處的元素。
來分析一下上述執行結果的原因:
當點選三次“新增”按鈕時,頁面中會渲染三次 元件內容,同時,父元件中的
list
陣列元素值變為 [1, 2, 3]
。當點選第一行中的刪除按鈕時,呼叫 remove()
方法將 list
陣列中的第一個元素刪除,則 list
[2, 3]
,然後檢視中重新使用 v-for
渲染,按鈕上的資料依賴於 list
中的元素值,所以被刪除掉。由於之前的檢視中已渲染過
元件三次,而
元件中的狀態資料不受 list
陣列中刪除元素的影響,根據“就地複用”策略,
被就地複用。但陣列中現在只有兩個元素,也就是
只會被渲染二次,所以檢視中的效果就是最後一行中的文字框資料被刪除,第一行的按鈕被刪除。
這樣的執行結果顯示不合理,怎麼解決這個問題呢,那就是新增 key
屬性。引用官方文件的話:
為了給 Vue 一個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,你需要為每項提供一個唯一
key
attribute
也就是說我們需要提供一個 key
屬性,告訴 Vue
每個節點的差異,以便能夠更好的跟蹤節點資訊。
<key-test v-for="(item, index) in list" :key="item"> <button @click="remove(index)">刪除{{item}}button>key-test>
使用 v-for
實現列表渲染時,動態繫結 key
屬性值,效果如下:
新增 key
後的效果就正常了,來分析一下原因。
這裡使用 list
陣列中的元素值作為 key
屬性值,點選三次“新增”按鈕後,list
陣列值為 [1, 2, 3]
。點選第一行的“刪除1”按鈕,list
陣列中將第一個元素刪除,變為 [2, 3]
,重新渲染時,發現 key=2
與 key=3
的節點沒有發生變化,而 key=1
的節點被刪除了,所以檢視中第一行的內容被刪除了,這符合我們的預期。
為什麼不用 index
作為 key
來使用呢?
如果使用 index
作為 key
:
<key-test v-for="(item, index) in list" :key="index"> <button @click="remove(index)">刪除{{item}}button>key-test>
測試效果:
和沒有新增 key
時的測試效果類似,這是為什麼呢?再分析一下原因。
仍然先點選三次“新增”按鈕,list
陣列中元素為 [1, 2, 3]
,下標分別為 0, 1, 2
,點選第一行的刪除按鈕,list
陣列元素變為 [2, 3]
,但陣列中下標會自動重新編號,下標變為 0, 1
,利用 v-for
重新渲染時,使用 index
作為 key
值,所以 key=0
與 key=1
的元素還在,而 key=2
的元素被刪除了,檢視渲染的效果如上圖所示,仍是最後一行文字框被刪除,顯然這又是不符合正常處理邏輯的。
因此,建議儘可能在使用 v-for
時為每項提供唯一的 key
屬性,並且不使用 index
作為 key
值。