vue的diff演算法學習

2021-09-13 22:30:33 字數 3652 閱讀 3358

原始碼位址

diff演算法首先要明確乙個概念就是diff的物件是虛擬dom,更新真實dom則是diff演算法的結果

constructor (

。。。)

這個部分的** 主要是為了更好地知道在diff演算法中具體diff的屬性的含義,當然也可以更好地了解vnode例項

核心函式是patch函式

isundef判斷(是不是undefined或者null)

// empty mount (likely as component), create new root elementcreateelm(vnode, insertedvnodequeue) 這裡可以發現建立節點不是乙個乙個插入,而是放入乙個佇列中統一批處理

核心函式samevnode

function samevnode (a, b)
這裡是乙個外層的比較函式,直接去比較了兩個節點的key,tag(標籤),data的比較(注意這裡的data指的是vnodedata),input的話直接比較type。

export inte***ce vnodedata ;

ref?: string;

tag?: string;

staticclass?: string;

class?: any;

staticstyle?: ;

style?: object | object;

props?: ;

attrs?: ;

domprops?: ;

hook?: ;

on?: ;

nativeon?: ;

transition?: object;

show?: boolean;

inlinetemplate?: ;

directives?: vnodedirective;

keepalive?: boolean;

}

這會確認兩個節點是否有進一步比較的價值,不然直接替換

替換的過程主要是乙個createelm函式 另外則是銷毀oldvnode

// destroy old node

if (isdef(parentelm)) else if (isdef(oldvnode.tag))

插入過程簡化來說就是判斷node的type分別呼叫

createcomponent(會判斷是否有children然後遞迴呼叫)

createcomment

createtextnode

建立後使用insert函式

之後需要用hydrate函式將虛擬dom和真是dom進行對映

function insert (parent, elm, ref) 

} else

}}

核心函式

function patchvnode (oldvnode, vnode, insertedvnodequeue, removeonly) 

const elm = vnode.elm = oldvnode.elm

if (istrue(oldvnode.isasyncplaceholder)) else

return

}if (istrue(vnode.isstatic) &&

istrue(oldvnode.isstatic) &&

vnode.key === oldvnode.key &&

(istrue(vnode.iscloned) || istrue(vnode.isonce))

) let i

const data = vnode.data

if (isdef(data) && isdef(i = data.hook) && isdef(i = i.prepatch))

const oldch = oldvnode.children

const ch = vnode.children

if (isdef(data) && ispatchable(vnode))

if (isundef(vnode.text)) else if (isdef(ch)) else if (isdef(oldch)) else if (isdef(oldvnode.text))

} else if (oldvnode.text !== vnode.text)

if (isdef(data))

}

const el = vnode.el = oldvnode.el 這是很重要的一步,讓vnode.el引用到現在的真實dom,當el修改時,vnode.el會同步變化。

這部分重點還是關注整個演算法

首先四個指標,oldstart,oldend,newstart,newend,兩個陣列,oldvnode,vnode。

function updatechildren (parentelm, oldch, newch, insertedvnodequeue, removeonly)  else if (isundef(oldendvnode))  else if (samevnode(oldstartvnode, newstartvnode))  else if (samevnode(oldendvnode, newendvnode))  else if (samevnode(oldstartvnode, newendvnode))  else if (samevnode(oldendvnode, newstartvnode))  else  else  else 

}newstartvnode = newch[++newstartidx]}}

if (oldstartidx > oldendidx) else if (newstartidx > newendidx)

}

乙個迴圈比較的幾種情況和處理(以下的++ --均指index的++ --)比較則是比較的node節點,簡略寫法 不嚴謹 比較用的是samevnode函式也不是真的全等

整體迴圈不結束的條件oldstartidx <= oldendidx && newstartidx <= newendidx

oldstart === newstart,oldstart++ newstart++

oldend === newend,oldend-- newend--

oldstart === newend, oldstart插到隊伍末尾 oldstart++ newend--

oldend === newstart, oldend插到隊伍開頭 oldend-- newstart++

剩下的所有情況都走這個處理簡單的說也就兩種處理,處理後newstart++

newstart在old中發現一樣的那麼將這個移動到oldstart前

沒有發現一樣的那麼建立乙個放到oldstart之前

迴圈結束後並沒有完成

還有一段判斷才算完

if (oldstartidx > oldendidx)  else if (newstartidx > newendidx)
簡單的說就是迴圈結束後,看四個指標中間的內容,old陣列中和new陣列中,多退少補而已

整體認識還很粗糙,不過以目前的水平和對vue的了解也就只能到這了

vue的diff演算法

1.當資料發生變化時,vue是怎麼更新節點的?渲染真實dom的開銷很大,比如我們修改了某個資料,如果直接渲染到真實dom會引起整個dom樹的重繪和重排,有沒有可能我們只更新我們修改的那一小塊dom而不更新整個dom呢?diff演算法可以幫助我們。我們根據真實dom生成乙個虛擬dom,當虛擬dom某個...

詳解vue的diff演算法

前言先來了解幾個點 1.當資料發生變化時,vue是怎麼更新節點的?要知道渲染真實dom的開銷是很大的,比如有時候我們修改了某個資料,如果直接渲染到真實dom上會引起整個dom樹的重繪和重排,有沒有可能我們只更新我們修改的那一小塊dom而不要更新整個dom呢?diff演算法能夠幫助我們。我們先根據真實...

vue的diff演算法理解

diff演算法作用 用來修改dom的一小段,不會引起dom樹的重繪diff演算法實現的原理 diff演算法將virtual dom的某個節點資料改變後生成的新的vnode與舊節點進行比較,並替換為新的節點,具體過程就是呼叫patch方法,比較新舊節點,一邊比較一邊給真實的dom打補丁進行替換func...