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 attributevue 在 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 ...