Vue列表渲染中的key值的重要性

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 .
16401a8ca6f8c764.jpg

1 .當(dāng)我們想把一個(gè)f插入到b,c之間朴肺,默認(rèn)是這樣的


16401a8ca73549bb.jpg

2 .一個(gè)頂一個(gè)窖剑,并不是我們想象的那樣,同理戈稿,刪除的時(shí)候也是這樣(c->f,d-c,e-d,然后插入e)
3 .但是如果我們給他加了key值之后


16401a8ca6d7e50c.jpg

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 .

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市揪漩,隨后出現(xiàn)的幾起案子旋恼,更是在濱河造成了極大的恐慌,老刑警劉巖奄容,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冰更,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡昂勒,警方通過(guò)查閱死者的電腦和手機(jī)蜀细,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)奠衔,“玉大人谆刨,你說(shuō)我怎么就攤上這事」榻铮” “怎么了她我?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)员淫。 經(jīng)常有香客問(wèn)我合蔽,道長(zhǎng),這世上最難降的妖魔是什么介返? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任拴事,我火速辦了婚禮,結(jié)果婚禮上圣蝎,老公的妹妹穿的比我還像新娘刃宵。我一直安慰自己,他們只是感情好徘公,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布牲证。 她就那樣靜靜地躺著,像睡著了一般关面。 火紅的嫁衣襯著肌膚如雪坦袍。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天等太,我揣著相機(jī)與錄音捂齐,去河邊找鬼。 笑死缩抡,一個(gè)胖子當(dāng)著我的面吹牛奠宜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瞻想,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼压真,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蘑险?” 一聲冷哼從身側(cè)響起滴肿,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎佃迄,沒(méi)想到半個(gè)月后嘴高,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體竿音,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡和屎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年拴驮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柴信。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡套啤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出随常,到底是詐尸還是另有隱情潜沦,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布绪氛,位于F島的核電站唆鸡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏枣察。R本人自食惡果不足惜争占,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望序目。 院中可真熱鬧臂痕,春花似錦、人聲如沸猿涨。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)叛赚。三九已至澡绩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間俺附,已是汗流浹背肥卡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昙读,地道東北人召调。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蛮浑,于是被迫代替她去往敵國(guó)和親唠叛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • MYSQL 基礎(chǔ)知識(shí) 1 MySQL數(shù)據(jù)庫(kù)概要 2 簡(jiǎn)單MySQL環(huán)境 3 數(shù)據(jù)的存儲(chǔ)和獲取 4 MySQL基本操...
    Kingtester閱讀 7,787評(píng)論 5 116
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,092評(píng)論 1 32
  • 楊帛翰沮稚,1月份艺沼,第五次,讀書(shū)打卡蕴掏。我讀的書(shū)名是:《西頓野生動(dòng)物障般,小說(shuō)全集之调鲸,泡泡野豬。 西內(nèi)華達(dá)山脈坐落在...
    楊帛翰閱讀 525評(píng)論 0 0
  • 提高時(shí)間管理,一般來(lái)說(shuō)有兩個(gè)方向定拟。一是提高做事的效率于微,二是去做更有價(jià)值的事。時(shí)間管理=事件的價(jià)值×做事的效率青自。 工...
    討喜的魚(yú)閱讀 525評(píng)論 0 1