題目來源:juejin.im/post/5d23e7…html
目標:經過面試題來讓本身的知識面更加廣,更加深刻。vue
首先咱們從官網的解釋出發:node
劃重點面試
上面這麼4點就是官方文檔中主要解釋的意思。吃透了以上幾點,也就知道了key是什麼以及他的做用。算法
diff算法咱們知道,他會判斷開始和結尾4個節點是不是相同的節點,而這個sameVnode第一步就是判斷兩個元素的key值。意味着key相同,它們纔有多是相同元素,不相同,直接返回false。api
這邊我只是截取了代碼片斷,這一步是將vnode的子元素數組,生成key-index的map,方便經過key去查找對應的index子元素,進行相同節點的比較。而它的上文是先後4個新舊節點兩兩對比不成功的狀況下,下文就是經過這個map去定位相同的元素。數組
聊到速度這個話題,咱們先能夠從本質上比較一下。bash
咱們用簡單的數據渲染的例子來看一下app
實例代碼以下:dom
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<div @click="changeData">切換數據</div>
<li v-for="item in list">{{ item.text }}</li>
</div>
<script src="../../dist/vue.min.js"></script>
<script type="module" crossorigin=「use-credentials」>
var app = new Vue({
el: '#app',
data: {
list: [],
list1: [],
list2: [],
nowDate: '',
updateTime: '',
},
created() {
for (let i = 0; i <= 100000; i++) {
this.list1.push({
id: i,
text: i
})
this.list2.push({
id: i * 2,
text: 100000 - i
})
}
this.list = this.list1
},
methods: {
changeData() {
this.nowDate = Date.now();
this.list = this.list2;
}
},
updated() {
const date = Date.now();
console.log(`updateTime: ${date - this.nowDate}`);
}
})
</script>
</body>
</html>
複製代碼
將上述遍歷的html代碼帶上key值。
<li v-for="item in list" :key="item.id">{{ item.text }}</li>
複製代碼
總結: 不帶key的速度是更快的。緣由有以下:在上述例子中,不帶key的省略了銷燬和建立dom的開銷,只須要替換文本節點就ok了,而帶key的卻須要進行patch流程,並且須要把能複用的那部分元素找出來,將不能複用的消除,而且從新建立新的dom元素。
既然咱們從上面檢測出來,是不帶key的會更快一點,那麼咱們爲何要帶key呢?
一、不帶key自己來講沒問題,可是當你遍歷的元素中,有組件的時候,就會發現問題。由於組件是能夠帶有自身狀態的。咱們來看一下下面這個例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<div v-for="(item, index) in list">
<component-a></component-a>
<button @click="deleteInput(index)">刪除</button>
</div>
</div>
<script src="../../dist/vue.min.js"></script>
<script type="module" crossorigin=「use-credentials」>
var ComponentA = {
data: function () {
return {
input: 0
}
},
template: '<input v-model="input" />'
}
var app = new Vue({
el: '#app',
data: {
list: ['1', '2', '3'],
},
methods: {
changeData() {
this.nowDate = Date.now();
this.list = this.list2;
},
deleteInput(index) {
this.list.splice(index, 1);
}
},
components: {
ComponentA
}
})
</script>
</body>
</html>
複製代碼
上述代碼很簡單,主要實現一下功能:
一、組件攜帶有本身狀態的input
二、頁面遍歷子組件生成3個input
複製代碼
而後點擊中間那個刪除,生成的結果:
指望的結果:
你們能夠綁key以後試一下,就是咱們指望的結果。
二、帶key的由於不是就地複用,因此能夠實現一些過渡的動畫效果。
平時咱們很喜歡用index去做爲key的索引,可是這樣的話,key值就失去了自己的意義,在遇到上述那幾個例子的時候,一樣回去踩坑。
不少集團項目中,會用到eslint去檢測template中v-for是否用了key值。從而減小錯誤率。那麼key最好和數據返回的id值去綁定。
這個知識點其實很淺,可是也改變了個人不少認知。
一、不必定不少時候都要寫key值,若是是簡單的列表渲染,我以爲大可沒必要。
二、當你要去寫key值的時候,最好不要用index,由於index這個值和就地複用沒啥區別。
三、當你要實現一些過渡效果的時候,不妨看一下vue的文檔,有一些現成的過渡效果能夠直接用。