Vue3中的執(zhí)行流程思路分析-流程圖
一. 前言
本文只在為大家梳理完整的vue3
代碼執(zhí)行流程,從創(chuàng)建createApp
到渲染為真實(shí)dom
節(jié)點(diǎn)。
在讀后續(xù)文章時(shí),請(qǐng)大家參考以下流程圖食用,好了廢話不多說(shuō),開(kāi)整?。。?/p>
(本文主要為梳理思路,不展示太多源碼。)
二. Vue3 思路分析
提示:一定要按照流程圖哦!?。?/p>
1. createRender(options)
我們創(chuàng)建vue3
時(shí),最常見(jiàn)的一個(gè)api
就是createApp
,但是在執(zhí)行createRender
時(shí),createApp
還沒(méi)有被創(chuàng)建,那該方法是干什么的呢,傳入的參數(shù)有是什么呢?我們接著往下看。
options
:源碼中也叫做 nodeOps
,其實(shí)就是vue3
自己重新封裝的一些dom
操作,例如insert、remove、createElement等
,在pc端,其實(shí)就是利用domcument
下的一些原生方法實(shí)現(xiàn)
優(yōu)點(diǎn):那就有人要問(wèn)了,為什么要重新封裝
首先有這么幾點(diǎn)好處:
- 1.封裝后使用更清楚簡(jiǎn)短,方便調(diào)用
- 2.最重要的一點(diǎn),那就是將
vue
的渲染工作與dom
操作完全解耦,這樣更適合多端操作,只需要重入對(duì)應(yīng)的nodeOps
即可,自己重新封裝對(duì)應(yīng)的dom
操作方法,比如移動(dòng)端等
從流程圖來(lái)看,調(diào)用該方法之后,返回三個(gè)Api
,其中我們只關(guān)心兩個(gè)重要的也是常用的createApp、render
我們繼續(xù)往下看。
2. createApp
這個(gè)方法大家應(yīng)該都不陌生,該方法傳入一個(gè)根組件rootComponent
,但是并沒(méi)有做任何處理,在該方法中主要任務(wù)創(chuàng)建了一個(gè)全局對(duì)象app
。
我們來(lái)看下app中常見(jiàn)的幾個(gè)api
:
App
use
: 用來(lái)注冊(cè)插件,為vue實(shí)現(xiàn)擴(kuò)展,如vueRouter、vuex、pinia等component
: 用來(lái)注冊(cè)全局組件,可以在任意組件中使用- 注意:以上方法都應(yīng)該在mount掛載之前執(zhí)行
mount
: 這一步也就是最關(guān)鍵的一部,開(kāi)始執(zhí)行將組件渲染的第一步,我們繼續(xù)往下看
3. app.mount(‘#app’)
從流程圖中我們可以看到,掛載中主要執(zhí)行了兩個(gè)操作
- 1.
createVNode
- 首先將我們傳入的根組件傳入到
createVNode
方法中,將組件包裝成vnode
對(duì)象并且返回 - 2.
render(vnode, rootContainer)
- 此處的
render
就是在前邊執(zhí)行createRender
時(shí)返回的方法,我們?cè)诖颂幚^續(xù)執(zhí)行它,并且傳入兩個(gè)參數(shù),第一個(gè)是我們包裝后的rootComponent
,第二個(gè)是掛載傳入真實(shí)domrootContainer
好了,mount
執(zhí)行完畢,我們進(jìn)入到render
中繼續(xù)向下執(zhí)行
4. render(vnode, container)
在此方法中,做了一個(gè)最重要的工作就是將已經(jīng)渲染的vnode
,也可以稱(chēng)之為舊的vnode
保存到container._vnode
上,然后調(diào)用
patch(container._vnode|| null, vnode)
這樣,就形成了新舊vnode
,也就有了diff
的說(shuō)法,讓我們進(jìn)入到patch
方法中。
5. patch(n1, n2, container)
patch
中文意思打補(bǔ)丁,也就描述了他的用法,對(duì)比新舊vnode
,也就是我們常說(shuō)的diff
算法,將新的vnode
渲染到真實(shí)dom中。
該方法中主要分為了兩大分支,當(dāng)然還有其它,我們就先忽略,跟著主線走下去
- 1.
processComponent
- 當(dāng)傳入的n2為組件時(shí)進(jìn)入這個(gè)分支
- 2.
processElement
- 當(dāng)傳入的n2為元素類(lèi)型時(shí)走該分支
我們先進(jìn)入processComponent
來(lái)對(duì)傳入的rootComponent
進(jìn)行處理
6. processComponent
該方法中又出現(xiàn)了兩個(gè)分支
mountComponent
: 在第一次掛載時(shí)執(zhí)行updateComponent
: 組件跟新時(shí)執(zhí)行
我們接著往下看
7. mountComponent
該組件中執(zhí)行了三個(gè)主要的方法,我們一個(gè)個(gè)來(lái)看
createInstance
:首先是創(chuàng)建實(shí)例,我們自定義的每個(gè)組件第一次渲染時(shí)都會(huì)走該分支,為每個(gè)組件定義了一個(gè)組件實(shí)例instance
,因此vue3
中就有了一個(gè)方法getCurrentInstance
來(lái)訪問(wèn)每個(gè)組件的實(shí)例。setupComponent
:這一步非常重要,該方法接受一個(gè)參數(shù),也就是剛剛創(chuàng)建的組件實(shí)例,在這一步中,調(diào)用了我們傳入的setup
,所以,我們調(diào)用的所有方法,也就是在這被執(zhí)行,比如reactive,ref,生命hook,watch,computed等
,之后將setup
調(diào)用的結(jié)果保存到instance
中的setupState
屬性中。setupRenderEffect
:在一切準(zhǔn)備工作都做完之后,接下來(lái)就該進(jìn)行渲染,我們繼續(xù)進(jìn)入到該方法中。
8. setupRenderEffect
該方法中創(chuàng)建了一個(gè)componentUpdateFn
組件更新函數(shù),也就是在這,實(shí)現(xiàn)了真正的響應(yīng)式處理,在setupComponent
中,執(zhí)行了setup
,在這我們對(duì)數(shù)據(jù)進(jìn)行了響應(yīng)式處理,利用reactive/refs
對(duì)數(shù)據(jù)實(shí)現(xiàn)了處理,在get
中收集依賴(lài),set
中更新依賴(lài)。
在創(chuàng)建好componentUpdateFn
方法之后,我們創(chuàng)建了一個(gè)新的對(duì)象
new ReactiveEffect(componentUpdateFn)
,之后我們執(zhí)行返回對(duì)象的run
方法,其中執(zhí)行了傳入的componentUpdateFn
函數(shù),在componentUpdateFn
中,我們首先對(duì)組件的render
或者template
進(jìn)行處理,也就對(duì)我們用到了響應(yīng)式數(shù)據(jù)進(jìn)行了get
,由此,將ReactiveEffect
收集到對(duì)應(yīng)數(shù)據(jù)的依賴(lài)中,在每次數(shù)據(jù)修改時(shí),執(zhí)行componentUpdateFn
,之后,在掛載函數(shù)中繼續(xù)執(zhí)行patch
,傳入處理后的render
或者temeplate
,至此回到patch
中,進(jìn)行遞歸。
9. patch
此時(shí),傳入的是根標(biāo)簽包裝后的vnode
,所以,此次走的分支為processElement
,讓我們跟著流程圖繼續(xù)往下看。
10. processElement mountElement
在該方法中,我們利用我們傳入的nodeOpts
,也就是dom操作方法,將vnode
渲染為真實(shí)的dom,此時(shí),終于將組件渲染到頁(yè)面上,同時(shí)將轉(zhuǎn)換的真實(shí)dom存放在vnode.el
上。
patchElement
該方法也就是diff
算法的核心,當(dāng)組件更新之后,通過(guò)diff
算法,將新的vnode
渲染到頁(yè)面上。
三. 結(jié)尾
至此,vue3從創(chuàng)建到渲染的所有流程執(zhí)行結(jié)束,在數(shù)據(jù)更新之后,我們通過(guò)執(zhí)行依賴(lài),也就是componentUpdateFn
函數(shù),重復(fù)之前的步驟,重新執(zhí)行組件的render函數(shù)
獲取根標(biāo)簽,傳遞給patch
,然后更新頁(yè)面,一直重復(fù)該過(guò)程。也就實(shí)現(xiàn)了頁(yè)面的改變。直到網(wǎng)頁(yè)關(guān)閉。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue實(shí)現(xiàn)二級(jí)導(dǎo)航欄效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)二級(jí)導(dǎo)航欄效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10vue引用CSS樣式實(shí)現(xiàn)手機(jī)充電效果
這篇文章主要介紹了vue引用CSS樣式實(shí)現(xiàn)手機(jī)充電效果,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01vue2基本響應(yīng)式實(shí)現(xiàn)方式之讓數(shù)組也變成響應(yīng)式
這篇文章主要介紹了vue2基本響應(yīng)式實(shí)現(xiàn)方式之讓數(shù)組也變成響應(yīng)式問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04Vue.js?element-plus使用圖標(biāo)不顯示問(wèn)題的解決方式
近期在學(xué)習(xí)Vue時(shí)用elementUI時(shí)發(fā)現(xiàn)圖標(biāo)在頁(yè)面上顯示不出來(lái),所以這篇文章主要給大家介紹了關(guān)于Vue.js?element-plus使用圖標(biāo)不顯示問(wèn)題的解決方式,需要的朋友可以參考下2022-09-09使用vue開(kāi)發(fā)移動(dòng)端管理后臺(tái)的注意事項(xiàng)
這篇文章主要介紹了使用vue開(kāi)發(fā)移動(dòng)端管理后臺(tái)的注意事項(xiàng),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03vue3限制table表格選項(xiàng)個(gè)數(shù)的解決方法
這篇文章主要為大家詳細(xì)介紹了vue3限制table表格選項(xiàng)個(gè)數(shù)的解決方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04Vue+Element實(shí)現(xiàn)頁(yè)面生成快照截圖
這篇文章主要為大家詳細(xì)介紹了Vue如何結(jié)合Element實(shí)現(xiàn)頁(yè)面生成快照截圖功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03解決vue admin element noCache設(shè)置無(wú)效的問(wèn)題
今天小編就為大家分享一篇解決vue admin element noCache設(shè)置無(wú)效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11使用Vue實(shí)現(xiàn)點(diǎn)擊按鈕小球加入購(gòu)物車(chē)動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了如何使用Vue實(shí)現(xiàn)點(diǎn)擊按鈕小球加入購(gòu)物車(chē)動(dòng)畫(huà),文中的示例代碼講解詳細(xì),有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03