源碼中找答案:src\core\vdom\patch.js - updateChildren()
測(cè)試代碼如下
<!DOCTYPE html>
<html>
<head>
<title>03-key的作用及原理?</title>
</head>
<body>
<div id="demo">
<p v-for="item in items" :key="item">{{item}}</p>
</div>
<script src="../../dist/vue.js"></script>
<script>
// 創(chuàng)建實(shí)例
const app = new Vue({
el: '#demo',
data: { items: ['a', 'b', 'c', 'd', 'e'] },
mounted () {
setTimeout(() => {
this.items.splice(2, 0, 'f')
}, 2000);
},
});
</script>
</body>
</html>
上面案例重現(xiàn)的是以下過程

11.jpg
不使用key

22.png
如果使用key
- // 首次循環(huán)patch A
ABCDE
ABFCDE - // 第2次循環(huán)patch B
BCDE
BFCDE - // 第3次循環(huán)patch E
CDE
FCDE - // 第4次循環(huán)patch D
CD
FCD - // 第5次循環(huán)patch C
C
FC - // oldCh全部處理結(jié)束,newCh中剩下的F,創(chuàng)建F并插入到C前面
結(jié)論
- key的作用主要是為了高效的更新虛擬DOM,其原理是vue在patch過程中通過key可以精準(zhǔn)判斷兩 個(gè)節(jié)點(diǎn)是否是同一個(gè),從而避免頻繁更新不同元素,使得整個(gè)patch過程更加高效,減少DOM操作量,提高性能。
- 若不設(shè)置key還可能在列表更新時(shí)引發(fā)一些隱蔽的bug
- vue中在使用相同標(biāo)簽名元素的過渡切換時(shí),也會(huì)使用到key屬性,其目的也是為了讓vue可以區(qū)分它們,否則vue只會(huì)替換其內(nèi)部屬性而不會(huì)觸發(fā)過渡效果。