Vue React列表元件中寫 key 原因

2022-09-12 10:12:13 字數 2701 閱讀 9710

vue 和 react 都是採用 diff 演算法來對比新舊虛擬節點,從而更新節點。

vue 文件原文:

當 vue 正在更新使用 v-for 渲染的元素列表時,它預設使用「就地更新」的策略。如果資料項的順序被改變,vue 將不會移動 dom 元素來匹配資料項的順序,而是就地更新每個元素,並且確保它們在每個索引位置正確渲染

也就是當資料改變時,dom 節點不會移動,而只是更新其內部的內容

方便理解「就地更新」的例子:

var vm = new vue(

})

**會生成 dom 節點陣列,每個節點標記唯一身份 id

[

'1', // id: a

'2', // id: b

'3', // id: c

'4', // id: d

'5' // id: e

]

當 datalist 中的資料改變時,有無 key 的區別

vm.datalist = [4, 1, 3, 5, 2] // 資料位置替換

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

[ '4

', // id: a

'1', // id: b

'3', // id: c

'5', // id: d

'2' // id: e

]// 有 key 的情況,dom 節點位置進行交換,但是內容沒有更新

[ '4

', // id: d

'1', // id: a

'3', // id: c

'5', // id: e

'2' // id: b

]

當 datalist 中的資料增刪時,有無 key 的區別

vm.datalist = [3, 4, 5, 6, 7] // 資料進行增刪

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

[ '3

', // id: a

'4', // id: b

'5', // id: c

'6', // id: d

'7' // id: e

]// 2. 有key的情況,節點刪除了 a, b 節點,新增了 f, g 節點

[ '3

', // id: c

'4', // id: d

'5', // id: e

'6', // id: f

'7' // id: g

]

這個預設的模式是高效的,但是只適用於不依賴子元件狀態或臨時 dom 狀態 (例如:表單輸入值) 的列表渲染輸出

也就是就地更新(沒有 key)只適用於簡單場景,會帶來一些隱藏的***,比如可能不會產生過渡效果,或者在某些節點有繫結資料(表單)狀態,會出現狀態錯位等。

為了給 vue 乙個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,你需要為每項提供乙個唯一 key attribute

vue 在 diff 演算法中進行新舊虛擬 dom 對比時,會根據新節點的 key 去對比舊節點陣列中的 key,從而找到相應舊節點(key => index 的 map 對映),如果沒找到就認為是乙個新增節點。如果沒有 key,那麼就會採用遍歷查詢的方式去找到對應的舊節點。顯然對映的速度更快。

vue diff 部分原始碼:

// vue src/core/vdom/patch.js

function updatechildren (parentelm, oldch, newch, insertedvnodequeue, removeonly) else

newstartvnode = newch[++newstartidx]

}}

建立 map 對映的函式

function createkeytooldidx (children, beginidx, endidx) 

for (i = beginidx; i <= endidx; ++i)

return map

}

遍歷尋找

// samevnode 是對比新舊節點是否相同的函式

function findidxinold (node, oldch, start, end)

}

key 的作用主要是在 vue 的虛擬 dom 演算法,在新舊 nodes 對比時辨識 vnodes,提高虛擬 dom 更新效率

幾種實際情況:

保證元件狀態正確

例子:乙個新聞列表,可點選列表項來將其標記為"已訪問"

不帶 key 屬性的情況下,在「娛樂新聞」下選中第二項然後切換到「社會新聞」,"社會新聞"裡的第二項也會是被選中的狀態,因為這裡復用了元件,保留了之前的狀態。解決辦法就是為列表項加上唯一 key

用於強制替換元素/元件而不是重複使用它

例子:

}

當 text 發生改變時,總是會被替換而不是被修改,因此會觸發過渡。

使用Antd元件在React中寫列表樣式

buyername 王路飛 tradername 託 tradermobile 15112341234 transfercode gh1234567890 asktime wed mar 27 2019 10 03 15 gmt 0800 remark 備註備註備註備註 orderstatestr ...

為什麼要在列表元件裡寫 Key ?

答案 主要是為了提公升同級的比較效率的。借用我在部落格上另外一篇 vue 2 渲染過程的圖 其中核心比對邏輯就是新老節點頭對頭,頭對尾,尾對頭,尾對尾,都判定非 samevnode,則拿著 key 去比對,若其中有被判定為 samevnode,則復用節點。反之需要刪除後再新增新節點。function...

flutter中的列表元件

列表布局是我們專案開發中最常用的一種布局方式。flutter 中我們可以通過 listview 來定義列表項,支援垂直和水平方向展示。通過乙個屬性就可以控制列表的顯示方向。列表有以下分類 在flutter中,類別元件 listview 包含以下可選引數 import package flutter ...