????????在寫vue代碼的時(shí)候檀轨,經(jīng)常有用到v-for這個(gè)指令來遍歷數(shù)組或者對象胸竞,官方文檔推薦我們在使用v-for的時(shí)候,加上key屬性参萄,并且說明這個(gè)key屬性必須是唯一標(biāo)識卫枝。key可加可不加,vue都做了處理讹挎,但是給到key屬性的校赤,在性能上會(huì)好一些吆玖,為什么呢,其實(shí)是和vue的虛擬DOM的Diff算法有關(guān)系马篮。
? ??????key屬性主要用在Vue的虛擬DOM算法沾乘,在新舊nodes對比時(shí)辨識VNodes ;
????????如果不使用key, Vue會(huì)使用一種最大限度減少動(dòng)態(tài)元素并且盡可能的嘗試就地修改/復(fù)用相同類型元素的算法;
????????而使用key時(shí)积蔚,它會(huì)基于key的變化重新排列元素順序意鲸,并且會(huì)移除/銷毀key不存在的元素;
????????首先烦周,看看vue是怎么處理有key和沒有key的:
沒有key屬性的時(shí)候尽爆,是怎么去更新DOM:執(zhí)行patchUnkeyedChildren這個(gè)方法:
????????這個(gè)方法就是比較新舊虛擬節(jié)點(diǎn)的長度,以少的長度為準(zhǔn)做patch比較读慎,如果如果舊的節(jié)點(diǎn)比新的多漱贱,就刪掉多余的節(jié)點(diǎn),如果舊的比新的少夭委,就創(chuàng)建新的節(jié)點(diǎn)幅狮。并且,如果節(jié)點(diǎn)類型相同但內(nèi)容不同株灸,就會(huì)保留節(jié)點(diǎn)但是更新內(nèi)容(patch函數(shù)做的操作)崇摄。
patch函數(shù)是做了什么
? ? ? ? 源碼中的位置如下,大致就是不同情況下慌烧,對vnode的處理(新增逐抑,更新,卸載)
有key屬性的時(shí)候屹蚊,是怎么去更新DOM:執(zhí)行patchKeyedChildren這個(gè)方法:
? ? ? ? 先從頭部開始遍歷厕氨,判斷新舊vnode是不是同一個(gè)節(jié)點(diǎn)(節(jié)點(diǎn)的type和key都相同),相同便patch汹粤,不相同就跳出循環(huán)來到第二步命斧。
? ? ????????判斷虛擬節(jié)點(diǎn)是否相同的方法是isSameVNodeType,key就是其中一個(gè)重要的判斷節(jié)點(diǎn)相同的依據(jù)嘱兼。
? ? ? ? 第二步就是從尾部開始遍歷国葬,相同的就進(jìn)行patch,不同就跳出循環(huán)
? ? ? ? 第三步是進(jìn)行掛載
? ? ? ? 第四步是進(jìn)行卸載
? ? ? ? 第五步是特殊的芹壕,如果中間是不明序列汇四,節(jié)點(diǎn)打亂了,有多了也有少了哪雕,那么會(huì)基于key的變化重新排列元素順序船殉,盡量復(fù)用相同的節(jié)點(diǎn)的前提下,移除/銷毀key不存在的元素斯嚎,掛載新增的節(jié)點(diǎn)利虫。
看完vue對于有key無key時(shí)更新dom的不同處理挨厚,很明顯,有key的時(shí)候糠惫,效率更高疫剃,所以官方才更推薦我們在使用v-for時(shí)綁定key。