Vue.js運(yùn)行機(jī)制全局概覽

先上一張vue內(nèi)部流程圖,然后我們來逐個(gè)分析里面的具體模塊和流程:
vue內(nèi)部流程圖.png

初始化及掛載

1.png

new Vue() 之后,Vue會調(diào)用_init函數(shù)進(jìn)行初始化,也就是圖中的init過程,它會初始化生命周期、事件、props、methods、data、computed與watch等。其中最重要的就是通過Object.defineProperty設(shè)置settergetter函數(shù),用來實(shí)現(xiàn)響應(yīng)式以及收集依賴。
初始化之后調(diào)用$mount會掛載組件,如果是運(yùn)行時(shí)編譯,即不存在render function但是存在template的情況,需要進(jìn)行編譯步驟。

編譯

2.png

compile編譯可以分成parse、optimizegenerate三個(gè)階段,最終需要得到render function。

parse 會用正則等干事解析template模板中的指令、class、style等數(shù)據(jù),形成AST。

optimize的主要作用是標(biāo)記static靜態(tài)節(jié)點(diǎn),這是Vue在編譯過程中的一處優(yōu)化,后面當(dāng)update更新界面時(shí),會有一個(gè)patch的過程,diff算法會直接跳過靜態(tài)節(jié)點(diǎn),從而減少了比較的過程,優(yōu)化了patch的性能。

generate 是將AST轉(zhuǎn)化為render function字符串的過程,得到的結(jié)果是render的字符串以及staticRenderFns字符串。

在經(jīng)歷過parse、optimizegenerate三個(gè)階段后,組件就會存在渲染VNode所需的render function了。

響應(yīng)式

接下來就是Vue.js響應(yīng)式的核心部分。

3.png

這里的settergetter之前就介紹了,在init的時(shí)候通過Object.defineProperty進(jìn)行綁定,他使得當(dāng)被設(shè)置的對象被讀取的時(shí)候回執(zhí)行g(shù)etter函數(shù),在被賦值的對象修改的時(shí)候回執(zhí)行setter函數(shù)。
當(dāng)render function被渲染的時(shí)候,因?yàn)闀x取所需對象的值,所以會觸發(fā)getter函數(shù)進(jìn)行依賴收集,依賴收集的目的是將觀察者Watcher對象放到當(dāng)前閉包中的訂閱者Dep的subs中,形成如下所示的一個(gè)關(guān)系。

5.png

在修改對象的值得時(shí)候,會觸發(fā)對應(yīng)得setter,setter通知之前依賴收集得到的Dep中的每一個(gè)Watcher,告訴它們自己的值改變了,需要重新渲染視圖,這時(shí)候這些Watcher就會調(diào)用update來更新視圖,當(dāng)然這中間還有一個(gè)patch的過程以及使用隊(duì)列來異步更新的策略。

Virtual DOM

render function會別轉(zhuǎn)化為VNode節(jié)點(diǎn)。Virtural DOM其實(shí)就是一個(gè)普通的JavaScript對象(VNode節(jié)點(diǎn))作為基礎(chǔ)的樹,用對象屬性來描述節(jié)點(diǎn),實(shí)際上他只是一層對真實(shí)DOM的抽象。最終可以通過一系列操作來使這棵樹映射到真實(shí)的環(huán)境上。由于Virtual DOM是以JavaScript對象為基礎(chǔ)而不依賴真實(shí)的平臺環(huán)境,所以使他有了跨平臺的能力,比如說瀏覽器、Weex、Node等。
比如下面這個(gè)例子:

{
    tag: 'div'
    children: [
        {
            tag: 'a',
            text: 'click me'
        }
    ]
}

渲染后可以得到:

<div>
    <a>click me</a>
</div>

這只是一個(gè)簡單的例子,實(shí)際上節(jié)點(diǎn)有更多的屬性來標(biāo)記節(jié)點(diǎn),比如isStatic(代表是否為靜態(tài)節(jié)點(diǎn))、isComment(代表是否為注釋節(jié)點(diǎn))等。

更新視圖

4.png

前面我們說到,在修改一個(gè)對象的值時(shí)候,會通過setter => Watcher => update的流程來修改對應(yīng)視圖,那么最終是如何更新視圖的呢?
當(dāng)數(shù)據(jù)變化時(shí),執(zhí)行render function就可以得到一個(gè)新的VNode節(jié)點(diǎn),我們?nèi)绻氲玫叫碌囊晥D,簡單的變化時(shí)直接解析這個(gè)新的VNode,然后全部渲染到真實(shí)DOM中,但是如果只對其中一小部分內(nèi)容作了修改,未免真?zhèn)€代價(jià)太大。
這時(shí)候我們就需要用到patch ,通過比較只修改這些有差異的DOM即可,為什么不直接對比DOM而是對弈Virtual DOM,因?yàn)镈OM的對應(yīng)性能遠(yuǎn)遠(yuǎn)大于直接對比JS對象。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容