? ? ? ?一直都想寫點東西,但是也許可能是因為懶惰,也許是文筆太爛,每當(dāng)要提筆寫的時候,總會有無從下手的感覺。想當(dāng)年,本人也是很喜歡的寫作的,不說奮筆疾書,起碼不會無從下手;然則,如今寫一個字都是難的??赡苁且驗椴饺肷鐣?,整個人變得越來越浮躁,一浮躁就無法靜下來來沉淀自己,無法思考,故而書寫能力甚至表達(dá)能力也越來越退化了......每思于此,痛徹心扉...... ? 閑話不說,步入正題。
? ? ?心血來潮,了解了下vue中的diff算法......
? ? ? ? 從源碼來看,vue在update的時候會調(diào)用如下函數(shù):

而其中的vm._patch_才是進(jìn)行vnode diff的核心,上面那個初始化render,后面這個是updates。
接下里進(jìn)入方法內(nèi)部:

核心是這段代碼,能優(yōu)化的地方就是在sameVnode(oldVnode, vnode)===true時。
里面核心

1.顯示抽離modules中的update或者h(yuǎn)ook中的update,進(jìn)行操作,主要是更新vnode中的attrs,class,dom-props,events,style,directives,refs...
2.如果vnode不是文本vnode,若oldVnode,和vnode都存在children的話,直接updateChildren;
? ? 若vnode children存在且oldVnode children不存在的話,則addVnodes添加整個vnode children對應(yīng)的新節(jié)點;若vnode children不存在且oldVnode children存在的話,則刪除oldVnode children對應(yīng)的舊節(jié)點;若vnode是文本,則如果vnode不是文本節(jié)點或者是文本節(jié)點但是text值不相等的時候,直接設(shè)置新節(jié)點的文本值;
3.updateChildren是如何update的呢,


如源碼所示,新舊節(jié)點序列(兄弟節(jié)點)的頭和尾都定義了兩個指標(biāo),目的是用來遍歷,那么如何遍歷呢?首先這四個節(jié)點必須存在,否則往后或者往前移動一位;然后oldVnode和新的vnode的頭尾兩個vnode兩兩進(jìn)行比較,如果是sameNode則進(jìn)行相應(yīng)的dom節(jié)點移動或者不移動,然后就是比較其子節(jié)點重復(fù)步驟二,指標(biāo)移動;再然后就是先抽取出oldVnode序列的帶有key的節(jié)點放在map中,然后再遍歷新的vnode序列,判斷該vnode的key是否在map中若在則找到該key對應(yīng)的oldVnode,如果此oldVnode與遍歷到的vnode 是sameVnode的話則復(fù)用dom并移動dom節(jié)點位置,并重復(fù)步驟二,否則就是重新創(chuàng)建新的dom節(jié)點,指標(biāo)移動。
綜上:描述的馬馬虎虎,也不知道看客們能否明白我的表達(dá).....哎,再次證明表達(dá)能力確實不行......
個人觀點,歡迎吐槽求踩:
? ? ? ? 光從diff來看的話,這個key的作用并不是很大,判斷復(fù)用dom節(jié)點的標(biāo)準(zhǔn)是sameVnode函數(shù),并不能光憑key值進(jìn)行判斷...從官方文檔上說,key的作用很大,甚至在!production的時候會有warn出現(xiàn),那肯定key在其他使用場景中發(fā)揮著更大的作用,可供后續(xù)研究......