1 .index值不是一定不變的,如果不加key值的話战虏,刪除前面的項(xiàng)拣宰。后面的index可能變也可能不變党涕,比如加個(gè)定時(shí)器的時(shí)候會(huì)變,不加定時(shí)器不會(huì)變
2 .不加key的話巡社,更新機(jī)制的進(jìn)行diff的時(shí)候是會(huì)全部比較的膛堤,比如刪除第一個(gè)的話,后面的元素其實(shí)都不一樣晌该,會(huì)一項(xiàng)一項(xiàng)的比較肥荔。然后全部元素都替換,沒(méi)有做到最小更新朝群。而且里面的傳的值也會(huì)變燕耿,如果這個(gè)時(shí)候你要根據(jù)里面的值刪除元素的話,就會(huì)出錯(cuò)姜胖,尤其是加了定時(shí)器之后
3 .所以這個(gè)key值對(duì)數(shù)據(jù)改變之后的diff更新比較有很大的性能提升誉帅,或者說(shuō)有了key和沒(méi)有key是兩種比較和更新機(jī)制
4 .使用v-for更新已渲染的元素列表時(shí),默認(rèn)采用舊地復(fù)用策略右莱,會(huì)復(fù)用之前的元素蚜锨,有的時(shí)候使用index來(lái)做為key值,其實(shí)不是特別推薦的慢蜓⊙窃伲可能會(huì)發(fā)生變化,最好是時(shí)間戳加上一個(gè)自增的數(shù)字
5 .如果有key的話晨抡,就會(huì)根據(jù)key值去判斷某個(gè)是否修改氛悬,重新渲染這一項(xiàng)
6 .虛擬dom的diff算法
1 .兩個(gè)相同的組件產(chǎn)生類(lèi)似的dom結(jié)構(gòu),不同的組件產(chǎn)生不同的dom結(jié)構(gòu)
2 .同一層級(jí)的一組節(jié)點(diǎn)凄诞,可以通過(guò)唯一的id進(jìn)行區(qū)分
3 .當(dāng)一層有很多相同的節(jié)點(diǎn)的時(shí)候圆雁,也就是列表節(jié)點(diǎn)時(shí),diff算法的更新過(guò)程默認(rèn)情況是遵循以上原則
4 .如果數(shù)據(jù)的順序被改變帆谍,Vue將不會(huì)移動(dòng)DOM元素在匹配數(shù)據(jù)項(xiàng)的順序,而是”就地更新“的策略轴咱。
7 .就地復(fù)用的弊端
1 .雖然很高效汛蝙,但是只適合與不依賴(lài)子組件狀態(tài)或者臨時(shí)的dom
2 .一旦要求新加入元素的狀態(tài),就會(huì)出問(wèn)題
3 .
1 .當(dāng)我們想把一個(gè)f插入到b,c之間朴肺,默認(rèn)是這樣的
2 .一個(gè)頂一個(gè)窖剑,并不是我們想象的那樣,同理戈稿,刪除的時(shí)候也是這樣(c->f,d-c,e-d,然后插入e)
3 .但是如果我們給他加了key值之后
4 .diff算法就可以正確的識(shí)別此節(jié)點(diǎn)西土,找到正確的位置并插入新的節(jié)點(diǎn)
5 .key的作用是為了更加高效的更新虛擬do'm,另外在vue中使用相同標(biāo)簽元素的過(guò)度切換的時(shí)候鞍盗,也需要使用key屬性需了,其目的是為了讓vue區(qū)分它們跳昼,否則vueh就只會(huì)替換其內(nèi)部屬性而不會(huì)觸發(fā)過(guò)度效果
第二波
1 .當(dāng)頁(yè)面的數(shù)據(jù)發(fā)生變化的時(shí)候,diff算法知乎i比較同一層級(jí)的節(jié)點(diǎn)
1 .如果節(jié)點(diǎn)類(lèi)型不同肋乍,直接干掉前面的節(jié)點(diǎn)鹅颊,在創(chuàng)建并插入新的節(jié)點(diǎn),不會(huì)在比較這個(gè)節(jié)點(diǎn)以后的子節(jié)點(diǎn)了
2 .如果節(jié)點(diǎn)類(lèi)型相同墓造,重新設(shè)置該節(jié)點(diǎn)的屬性堪伍,從而實(shí)現(xiàn)節(jié)點(diǎn)的更新
3 .所以,當(dāng)某一層有很多相同的節(jié)點(diǎn)的時(shí)候觅闽,diff的默認(rèn)是遵循第二條的
2 .對(duì)象遍歷渲染的時(shí)候帝雇,是按照Object.keys()結(jié)果遍歷的,所以不能保證絕對(duì)的順序蛉拙。所以最好是按照數(shù)組里面包含對(duì)象的方法來(lái)渲染摊求,這樣可以保證絕對(duì)的順序
3 .官方文檔的明確顯示的部分
1 .當(dāng)使用v-for更新已經(jīng)渲染過(guò)的元素列表時(shí),默認(rèn)的使用”舊地復(fù)用“策略刘离,如果數(shù)據(jù)項(xiàng)的順序被改變室叉,Vue是不會(huì)移動(dòng)dom來(lái)匹配數(shù)據(jù)項(xiàng)的順序,而是簡(jiǎn)單的復(fù)用此處的每個(gè)元素硫惕,并且確保他在特定索引下顯示已被渲染過(guò)的元素
2 .這個(gè)模式默認(rèn)是高效的茧痕,但是只適用于不依賴(lài)子組件狀態(tài)或臨時(shí)DOM鉆港臺(tái),比如列表渲染輸出
3 .為了給Vue一個(gè)提示恼除,使他可以追蹤每個(gè)節(jié)點(diǎn)的身份踪旷,從而重用和重新排序現(xiàn)有元素,這就需要為每一個(gè)項(xiàng)提供一個(gè)唯一的key屬性
4 .注意:不添加key的性能其實(shí)更加優(yōu)秀豁辉。除了想要性能或者輸出非常的內(nèi)容非常簡(jiǎn)單
5 .不要使用對(duì)象或者數(shù)組之類(lèi)的非原始值作為v-for的key令野,用字符串或者整數(shù)類(lèi)型的值來(lái)取代
4 .數(shù)據(jù)的這些方法會(huì)返回一個(gè)新的數(shù)據(jù),也就是說(shuō)當(dāng)調(diào)用這些方法的時(shí)候需要使用新數(shù)組替換舊的數(shù)組徽级。Vue為了使得dom元素得到最大范圍的重用而實(shí)現(xiàn)了一些智能的气破,啟發(fā)式的方法。也就是說(shuō)餐抢,用一個(gè)含有相同元素的數(shù)據(jù)去替換原來(lái)的數(shù)據(jù)會(huì)有非常高效的操作
5 .不能檢測(cè)到的變化:數(shù)組里面使用索引設(shè)置一個(gè)項(xiàng)時(shí)现使,包括對(duì)象添加新的值的時(shí)候,所以這兩種情況都需要使用特定的方法旷痕。只不過(guò)是不支持常用的用法罷了碳锈,當(dāng)時(shí)為什么不加個(gè)語(yǔ)法糖呢。欺抗。
6 .同一個(gè)元素里面v-for和v-if的優(yōu)先級(jí),v-if將運(yùn)行于每一個(gè)v-for循環(huán)中售碳,當(dāng)想根據(jù)某些條件在渲染一些dom的時(shí)候,舊可以使用這個(gè)
7 . v-if當(dāng)父元素 v-for當(dāng)子元素
v-if中的key
1 .v-if中想要渲染多個(gè)元素的時(shí)候,可以把一個(gè)template元素當(dāng)成不可見(jiàn)的包裹元素贸人,并在上面使用v-if间景,最終的渲染結(jié)果將不會(huì)包括template元素
2 .為了盡可能高效的渲染元素,通常會(huì)復(fù)用已有元素而不是從頭開(kāi)始渲染灸姊,除了更快拱燃,還以一些其他的好處
1 .以下是沒(méi)有key的時(shí)候
2 .input切換的時(shí)候,會(huì)保留之前填的表格
3 .
3 .添加一個(gè)key值力惯,vue就知道這兩個(gè)元素是完全不一樣的碗誉,所以創(chuàng)建的時(shí)候直接從0開(kāi)始,而不是復(fù)用
4 .但是如果其他的地方?jīng)]加key父晶,也是會(huì)復(fù)用的哮缺。所以要在合適的位置加上key
5 .v-show:帶有v-show的元素始終會(huì)被渲染并保留在dom中,v-show只是簡(jiǎn)單的切換css屬性display
6 .不支持template甲喝,也不支持v-else
比較v-show,v-if
1 .v-if是真正的條件渲染因?yàn)樗_保在切換過(guò)程中條件塊內(nèi)的事件監(jiān)聽(tīng)器和子組件適當(dāng)?shù)谋讳N(xiāo)毀和重建
2 .v-if也是惰性的尝苇,如果在初始渲染時(shí)條件為假,則什么都不做埠胖,直到條件第一次變?yōu)檎婵妨铮艜?huì)開(kāi)始渲染條件塊
3 .v-show:不管是什么條件,都是會(huì)被渲染直撤,只是簡(jiǎn)單的進(jìn)行css切換
4 .v-if有更高的切換開(kāi)銷(xiāo)非竿,v-show有更高的初始渲染開(kāi)銷(xiāo)。如果需要頻繁的切換谋竖,使用v-show,如果在運(yùn)行時(shí)條件很少改變红柱,則使用v-if較好
5 .
第三波,為什么加了key還是會(huì)復(fù)用呢蓖乘,沒(méi)有走到mounted生命周期
//父組件
<template>
<div>
<h1 @click="handleAdd">+</h1>
<h1 @click="handleRem">-</h1>
<test v-for="c in test_arr" :value="c.value" :key="c.id"/>
</div>
</template>
<script>
import test from './son/test'
export default{
data:function(){
return {
arr:[
{
id:1,
value:1
},
{
id:2,
value:2
},
{
id:3,
value:3
},
{
id:4,
value:4
},
{
id:5,
value:5
},
{
id:6,
value:6
},
{
id:7,
value:7
},
{
id:8,
value:8
},
{
id:9,
value:9
},
{
id:10,
value:10
},
{
id:11,
value:11
},
{
id:12,
value:12
},
{
id:13,
value:13
},
{
id:14,
value:15
},
{
id:15,
value:15
},
],
test_arr:[],
start:0
}
},
methods:{
handleAdd(){
this.start++
this.test_arr=this.arr.slice(this.start,this.start+3)
},
handleRem(){
this.start--
this.test_arr=this.arr.slice(this.start,this.start+3)
}
},
components:{
test,
}
}
</script>
1 .在第一次v-for中锤悄,不加key的話,如果數(shù)據(jù)改變的話嘉抒,其實(shí)走的是復(fù)用的邏輯零聚,并不走的第一次從新渲染的步驟,也就是沒(méi)有新創(chuàng)建dom結(jié)構(gòu)众眨,僅僅是替換了元素握牧,那么這個(gè)時(shí)候,當(dāng)我想根據(jù)新傳入的數(shù)據(jù)做一些操作的行為就不會(huì)觸發(fā)娩梨。其實(shí)這個(gè)情況是前后數(shù)據(jù)結(jié)構(gòu)一樣的。那如果前后數(shù)據(jù)結(jié)構(gòu)不一樣览徒,必然有新創(chuàng)建dom的情況狈定,也不會(huì)觸發(fā)mounted事件么?測(cè)試發(fā)現(xiàn),真的是不會(huì)觸發(fā)的
2 .然后我們加上了key值纽什,現(xiàn)在進(jìn)行數(shù)據(jù)改變措嵌,這時(shí)發(fā)現(xiàn),之后每一次變化的元素芦缰,才會(huì)觸發(fā)mounted事件企巢,也就是說(shuō),如果之前是顯示在第二個(gè)的元素让蕾,現(xiàn)在數(shù)據(jù)發(fā)生變化之后浪规,我們是沒(méi)辦法知道新的第一個(gè)元素的數(shù)據(jù),僅僅是通過(guò)mounted事件,只有新加入的元素探孝,才會(huì)觸發(fā)mounted事件
3 .那這個(gè)時(shí)候我們就需要使用一個(gè)新的生命周期函數(shù)笋婿,update。比如以下場(chǎng)景:當(dāng)傳入組件的某一個(gè)值發(fā)生了變化顿颅,導(dǎo)致渲染元素的高度發(fā)生了變化缸濒,而我們又恰恰想知道新的高度。這個(gè)時(shí)候就需要在updated生命周期函數(shù)里面觸發(fā)粱腻,然后改變記得這個(gè)變量
4 .這里其實(shí)第一次想的還是有點(diǎn)問(wèn)題的庇配,新加入的元素直接就新建就可以,不需要在復(fù)用dom绍些,重新渲染捞慌,然后在算一遍高度了。
//子組件
<template>
<div>
{{value}}
</div>
</template>
<script>
export default {
props:{
value:{
type:Number,
}
},
mounted(){
console.log('加載了一次')
console.log(this.value)
}
}
</script>
總結(jié)
1 .key的作用是用來(lái)對(duì)比組件自身新舊DOM進(jìn)行更新的,跟蹤節(jié)點(diǎn)身份
2 .key的作用是輔助判斷新舊vdom節(jié)點(diǎn)在邏輯上是不是同一對(duì)象遇革。
3 .默認(rèn)行為性能上會(huì)有提升卿闹?建議盡可能在使用 v-for 時(shí)提供 key attribute,除非遍歷輸出的 DOM 內(nèi)容非常簡(jiǎn)單萝快,或者是刻意依賴(lài)默認(rèn)行為以獲取性能上的提升锻霎。官網(wǎng)文檔
4 .