[Vue.js進(jìn)階]從源碼角度剖析Vue的生命周期

image

前言

使用Vue在日常開發(fā)中會(huì)頻繁接觸和使用生命周期,在官方文檔中是這么解釋生命周期的:

每個(gè) Vue 實(shí)例在被創(chuàng)建時(shí)都要經(jīng)過一系列的初始化過程——例如,需要設(shè)置數(shù)據(jù)監(jiān)聽、編譯模板、將實(shí)例掛載到 DOM 并在數(shù)據(jù)變化時(shí)更新 DOM 等蟀悦。同時(shí)在這個(gè)過程中也會(huì)運(yùn)行一些叫做生命周期鉤子的函數(shù)浙炼,這給了用戶在不同階段添加自己的代碼的機(jī)會(huì)季俩。

好比人的生老病死的過程,Vue同樣也有從組建初始化到組件掛載,組件更新,組件銷毀的一系列過程,而生命周期鉤子,是一個(gè)函數(shù),可以讓開發(fā)者在Vue到達(dá)某個(gè)時(shí)間段的時(shí)候做一些事情

最常見的就是在mounted鉤子中發(fā)送ajax請(qǐng)求獲取當(dāng)前的頁面組件所需要的數(shù)據(jù)

image

但是對(duì)于Vue.js進(jìn)階來說,只知道生命周期的拼寫和對(duì)應(yīng)的觸發(fā)時(shí)機(jī)肯定是不夠的,為什么鉤子函數(shù)不能是一個(gè)箭頭函數(shù),為什么在data中有時(shí)候無法獲取定義的數(shù)據(jù),我們通過this獲取data中的數(shù)據(jù)真的直接保存在this下了嗎酪我,Vue又是怎么做到無感知的事件監(jiān)聽/事件解綁

在這篇文章中,我將會(huì)帶大家深入Vue的源碼,從源碼中分析Vue的生命周期

文中的源碼截圖只保留核心邏輯 完整源碼地址

Vue版本:2.5.21

源碼概覽

image

當(dāng)我們?cè)趍ain.js中實(shí)例化Vue的時(shí)候欺矫,會(huì)經(jīng)過一些邏輯,然后進(jìn)入到_init函數(shù)開始Vue的生命周期,其實(shí)從這些函數(shù)的命名方式中就能大致看出Vue是如何運(yùn)行的了,接下來我們逐個(gè)分析每個(gè)函數(shù)具體做了什么

合并配置項(xiàng)

從上面的圖中能看到,在生命周期中第一件事就是合并配置項(xiàng),而對(duì)于根實(shí)例和組件實(shí)例,Vue的處理方式是不同的(在main.js中new Vue生成的是根實(shí)例,其余全部都是組件實(shí)例),根實(shí)例傳入的options參數(shù)里不會(huì)有_isComponent屬性,反之為true(實(shí)例化的時(shí)機(jī)不同,傳入的參數(shù)也不同,感興趣的朋友可以查看相關(guān)實(shí)例化的文章)

image

為了不必要的干涉络它,這里沒有引入vue-router,vuex

根實(shí)例合并配置項(xiàng)

對(duì)于根實(shí)例會(huì)走false的邏輯,進(jìn)入mergeOptions函數(shù)迂烁,合并Vue的各個(gè)配置項(xiàng)options,比如mixins,props,methods,watch,computed,生命周期鉤子等等,這是整個(gè)項(xiàng)目中第一次的合并配置。Vue會(huì)將所有的合并策略都保存在一個(gè)strats對(duì)象中,然后依次遍歷當(dāng)前實(shí)例和parent的同一個(gè)屬性,再去starts找那個(gè)屬性對(duì)應(yīng)的合并策略

通過斷點(diǎn)可以看到strats保存了很多合并的策略


image

我們沒有必要每個(gè)合并策略都去看一遍椰于,盡量把精力放在整個(gè)流程中怠益,不要撿了芝麻丟了西瓜。第一次的合并中瘾婿,Vue會(huì)通過resolveConstructorOptions(vm.constructor)獲取Vue構(gòu)造器的靜態(tài)屬性options作為parent蜻牢,這個(gè)options包含了一些預(yù)先設(shè)置好的配置項(xiàng),而child就是我們給根實(shí)例實(shí)例化的時(shí)候傳入的一些參數(shù)憋他,對(duì)應(yīng)例子中上圖的render函數(shù)

Vue預(yù)先設(shè)置的配置項(xiàng)作為第一次的parent:


image

根實(shí)例實(shí)例化傳入的參數(shù):

image

根實(shí)例的合并策略其實(shí)很簡(jiǎn)單孩饼,主要就是把Vue框架內(nèi)置的一些配置項(xiàng)和開發(fā)者在main.js中實(shí)例化Vue構(gòu)造器傳入的參數(shù)進(jìn)行一次簡(jiǎn)單的合并,作為根實(shí)例的$options屬性

組件實(shí)例合并配置項(xiàng)

組件實(shí)例合并配置項(xiàng)并不在_init函數(shù)中竹挡,因?yàn)榻M件實(shí)例和根實(shí)例不同镀娶,組件實(shí)例是由組件構(gòu)造器實(shí)例化的,而根實(shí)例是由Vue構(gòu)造器實(shí)例化的揪罕,而組件構(gòu)造器又是繼承自Vue的它需要通過Vue.extend方法去繼承Vue構(gòu)造函數(shù)梯码,我畫了張圖方便理解

image

Vue這么做符合面向?qū)ο蟮脑O(shè)計(jì)模式宝泵,一個(gè)組件實(shí)質(zhì)上是一個(gè)構(gòu)造器函數(shù)(進(jìn)一步可以認(rèn)為是一個(gè)class),這樣在一個(gè)頁面中引入多個(gè)相同的組件只需要多次實(shí)例化組件構(gòu)造器就可以了轩娶,并且可以做到實(shí)例之間互相獨(dú)立

而面向?qū)ο罅硗庖粋€(gè)好處就是可以實(shí)現(xiàn)繼承儿奶,體現(xiàn)在Vue框架中則是將組件構(gòu)造器繼承Vue構(gòu)造器,從而組件構(gòu)造器能夠獲得Vue構(gòu)造器內(nèi)置的一些配置項(xiàng)

組件實(shí)例合并配置項(xiàng)在src/core/global-api/extend.js,同樣會(huì)調(diào)用mergeOptions組件實(shí)例合并配置項(xiàng)會(huì)將Vue框架內(nèi)置的配置項(xiàng)和當(dāng)前組件配置項(xiàng)進(jìn)行合并并賦值給組件構(gòu)造器的靜態(tài)屬性options

image

再次回到mergeOptions中,這里就只例舉一個(gè)生命周期的合并策略鳄抒,直接貼上源碼并附上流程圖方便理解

image
image

這里我用了父級(jí)而不是父組件闯捎,因?yàn)閂ue的組件一般繼承自Vue構(gòu)造函數(shù)而不是父組件,通過流程圖可以發(fā)現(xiàn)许溅,Vue會(huì)保證生命周期函數(shù)始終是一個(gè)數(shù)組瓤鼻,并且以父=>子的順序排列的,Vue在執(zhí)行某個(gè)生命周期的時(shí)候會(huì)遍歷這個(gè)數(shù)組依次執(zhí)行函數(shù)贤重,所以當(dāng)我們?cè)赩ue構(gòu)造器和組件構(gòu)造器中的同一個(gè)生命周期里都定義了生命周期函數(shù)茬祷,會(huì)先執(zhí)行Vue構(gòu)造器中的那個(gè)

繼承了Vue構(gòu)造器后才會(huì)實(shí)例化子組件生成組件實(shí)例,再進(jìn)入到_init函數(shù)并蝗,這個(gè)時(shí)候_isComponent為true會(huì)執(zhí)行initInternalComponent祭犯,它會(huì)給組件實(shí)例創(chuàng)建$options屬性,指向子組件構(gòu)造器的靜態(tài)屬性options滚停,這樣就能夠通過組件實(shí)例的$options屬性訪問到當(dāng)前組件的配置項(xiàng)以及Vue框架內(nèi)置的配置項(xiàng)(包括全局組件沃粗,全局混入)

小結(jié)

  • 生命周期中第一件事就是合并配置項(xiàng),對(duì)于根實(shí)例和組件實(shí)例合并的時(shí)機(jī)不同
  • 根實(shí)例是在new Vue的時(shí)候進(jìn)行合并键畴,將Vue內(nèi)置的配置項(xiàng)和new Vue傳入的配置項(xiàng)進(jìn)行合并
  • 對(duì)于組件實(shí)例來說陪每,先會(huì)創(chuàng)建子組件的構(gòu)造器,并且調(diào)用Vue.extend繼承Vue構(gòu)造器镰吵,繼承的時(shí)候?qū)ue內(nèi)置的配置項(xiàng)和組件配置項(xiàng)進(jìn)行合并,并將結(jié)果保存在構(gòu)造器的options屬性中挂签,之后在創(chuàng)建組件實(shí)例的時(shí)候進(jìn)入initInternalComponent方法會(huì)將組件實(shí)例的$options指向組件構(gòu)造器的options屬性
  • Vue框架會(huì)根據(jù)不同的配置執(zhí)行不同的合并策略

代理開發(fā)環(huán)境的錯(cuò)誤

非生產(chǎn)環(huán)境下會(huì)進(jìn)入initProxy函數(shù)疤祭,通過ES6的Proxy給vm實(shí)例做一層攔截,主要作用是給開發(fā)環(huán)境下一些不合理的配置做出一些自定義的警告

image

上面的報(bào)錯(cuò)很多開發(fā)者都遇到過饵婆,其實(shí)就是在這個(gè)時(shí)候通過Proxy的has攔截器勺馆,當(dāng)某個(gè)屬性不在vm實(shí)例上卻被模版引用的時(shí)候,Vue會(huì)給出一些友好的提示

初始化自定義事件

隨后進(jìn)入initLifecycle侨核,這部分沒什么好講的草穆,初始化實(shí)例的一些生命周期的狀態(tài)和一些額外屬性,接著會(huì)進(jìn)入初始化組件的自定義事件

image

initEvents只會(huì)掛載自定義事件搓译,即組件中使用v-on監(jiān)聽的非native的事件(原生的DOM事件并非在initEvents中掛載)悲柱。Vue會(huì)把這些父組件中聲明的自定義的事件保存在子組件的_parentListeners屬性中(vm是子組件的組件實(shí)例,_parentListeners是在initInternalComponent中定義的)

進(jìn)入updateComponentListeners,發(fā)現(xiàn)Vue會(huì)調(diào)用add函數(shù)注冊(cè)所有的自定義事件些己,而對(duì)于組件來說add函數(shù)就會(huì)調(diào)用$on來達(dá)到監(jiān)聽自定義事件的效果

//https://github.com/vuejs/vue/blob/dev/src/core/instance/events.js#L24
function add (event, fn) {
  target.$on(event, fn)
}

//https://github.com/vuejs/vue/blob/dev/src/core/vdom/helpers/update-listeners.js#L83
//調(diào)用add注冊(cè)自定義事件(后面3個(gè)參數(shù)可忽略)
add(event.name, cur, event.capture, event.passive, event.params)

beforeCreate

添加完自定義事件后豌鸡,進(jìn)入initRender嘿般,定義插槽和給render函數(shù)的參數(shù)createElement,另外會(huì)將Vue的$attrs,$listeners變成響應(yīng)式的屬性

接著會(huì)執(zhí)行callHook(vm, 'beforeCreate')涯冠,從字面上來看就能猜出Vue在這個(gè)時(shí)候會(huì)調(diào)用beforeCreate這個(gè)生命周期函數(shù)炉奴,在之前合并配置項(xiàng)的時(shí)候就提到,生命周期函數(shù)最終會(huì)被包裹成一個(gè)數(shù)組蛇更,所以事實(shí)上Vue也支持這么寫

image

callHook函數(shù)會(huì)根據(jù)傳入的參數(shù)拿到$options屬性中對(duì)應(yīng)的生命周期函數(shù)組成的數(shù)組瞻赶,這里傳入了beforeCreate,所以會(huì)獲得beforeCreate中定義的所有生命周期函數(shù)派任,之后順序遍歷并且用call方法給每個(gè)生命周期函數(shù)綁定了this上下文砸逊,這就是為什么生命周期函數(shù)不能使用剪頭函數(shù)書寫的原因

image

初始化數(shù)據(jù)

接著執(zhí)行initInjections,這部分是用來初始化inject這個(gè)api吨瞎,由于日常開發(fā)使用頻率較少就不詳細(xì)解釋了(其實(shí)是我懶得研究-.-)

隨后會(huì)進(jìn)入另外一個(gè)關(guān)鍵的函數(shù)initState痹兜,它會(huì)依次初始化props,methods,data,computed,watch,我們一個(gè)個(gè)來講解

props

組件之間通信的時(shí)候颤诀,父組件給子組件傳參字旭,子組件需要定義props來接受父組件傳過來的屬性,而Vue規(guī)定崖叫,子組件是不能修改父組件傳來的props遗淳,因?yàn)檫@違背了單項(xiàng)數(shù)據(jù)流,會(huì)導(dǎo)致組件之間非常難以管理心傀,如果在子組件修改了props屈暗,Vue會(huì)發(fā)出一個(gè)警告

而Vue又是怎么知道開發(fā)者修改了props的屬性呢?原因還是利用了訪問器描述符setter

image

了解過響應(yīng)式原理的朋友應(yīng)該對(duì)這個(gè)有所熟悉脂男,Vue會(huì)將props對(duì)象變成一個(gè)響應(yīng)式對(duì)象养叛,并且第四個(gè)參數(shù)是一個(gè)自定義的setter,當(dāng)props被修改了會(huì)觸發(fā)這個(gè)setter宰翅,一單違背了單項(xiàng)數(shù)據(jù)流時(shí)就會(huì)報(bào)出這個(gè)警告

methods

對(duì)于methods弃甥,Vue會(huì)定義一些開發(fā)過程中的不規(guī)范的警告,隨后會(huì)將所有的method綁定vm實(shí)例汁讼,這樣我們就可以直接通過this獲取當(dāng)前的vm實(shí)例

data

到了最關(guān)鍵的data淆攻,data中一般保存的是當(dāng)前組件需要使用的數(shù)據(jù),除了根實(shí)例之外嘿架,組件實(shí)例的data一般都是一個(gè)函數(shù)瓶珊,因?yàn)镴S引用類型的特點(diǎn),如果使用對(duì)象耸彪,當(dāng)存在多個(gè)相同的組件伞芹,其中一個(gè)組件修改了data數(shù)據(jù),會(huì)反映到所有的組件蝉娜。當(dāng)data作為一個(gè)函數(shù)返回一個(gè)對(duì)象時(shí)丑瞧,每次執(zhí)行都會(huì)生成一個(gè)新的對(duì)象柑土,可以有效的解決這個(gè)問題

image

初始化data會(huì)執(zhí)行initData這個(gè)函數(shù),內(nèi)部會(huì)執(zhí)行定義的data函數(shù)并且把當(dāng)前實(shí)例作為this值绊汹,并且賦值給_data這個(gè)內(nèi)部屬性,值得注意的是稽屏,在執(zhí)行data函數(shù)的過程中是獲取不到computed中的數(shù)據(jù),因?yàn)閏omputed中的數(shù)據(jù)此時(shí)還沒初始化

image

隨后執(zhí)行proxy函數(shù)西乖,它的作用是將vm._data的屬性映射到vm屬性上狐榔,起到了"代理"的作用,這樣做是為了在開發(fā)過程中直接書寫this[key]的形式获雕,其原理依舊是利用了getter/setter薄腻,當(dāng)我們?cè)L問this[key]的時(shí)候會(huì)觸發(fā)getter,直接指向this._data[key]届案,setter同理

有人會(huì)問庵楷,那為啥不直接寫在vm實(shí)例上呢?因?yàn)槲覀冃枰獙?shù)據(jù)放在一個(gè)統(tǒng)一的對(duì)象上進(jìn)行管理楣颠,為的是下一步把_data通過observe變成一個(gè)響應(yīng)式對(duì)象尽纽。而為了在開發(fā)的時(shí)候書寫更加簡(jiǎn)潔,Vue采取了這種方法童漩,非常的討巧

computed

到了初始化computed弄贿,Vue會(huì)給每個(gè)計(jì)算屬性生成一個(gè)computed watcher,只有當(dāng)這個(gè)計(jì)算屬性的依賴項(xiàng)改變了才會(huì)去通知computed watcher更新這個(gè)計(jì)算屬性矫膨,從而既能達(dá)到實(shí)時(shí)更新數(shù)據(jù)差凹,又不會(huì)浪費(fèi)性能,也是Vue非常棒的功能

image

watch

初始化watch的時(shí)候最終會(huì)調(diào)用$watch方法侧馅,生成一個(gè)user watcher危尿,當(dāng)監(jiān)聽的屬性發(fā)生改變就會(huì)立即通知user watcher執(zhí)行回調(diào)

created

再調(diào)用initProvide初始化provide后就會(huì)執(zhí)行callHook(vm, 'beforeCreate'),和beforeCreate一樣,依次遍歷定義在$options上的created數(shù)組馁痴,執(zhí)行生命周期函數(shù)

至此整個(gè)組件創(chuàng)建完畢脚线,其實(shí)這個(gè)時(shí)候就可以和后端進(jìn)行交互獲取數(shù)據(jù)了,但是對(duì)于真正的DOM節(jié)點(diǎn)還沒有被渲染出來弥搞,一些需要和DOM的交互操作還無法在created鉤子中執(zhí)行,即無法在created鉤子中有操作生成視圖的DOM

掛載過程

回到_init函數(shù)渠旁,已經(jīng)到了最后一行攀例,會(huì)判斷$options是否有el屬性,在Vue-cli2的時(shí)候顾腊,cli會(huì)自動(dòng)在new Vue的時(shí)候傳入el參數(shù)粤铭,而對(duì)于Vue-cli3并沒有這么做,而是生成根實(shí)例后主動(dòng)調(diào)用$mount并傳入了掛載的節(jié)點(diǎn)杂靶,其實(shí)兩者都是一樣的梆惯,也可以使用$mount來實(shí)現(xiàn)組件的手動(dòng)掛載

Vue-cli2:


image

Vue-cli3:


image

$mount最終會(huì)執(zhí)行mountComponent這個(gè)函數(shù)

image

剛剛從_init的長(zhǎng)篇大論中逃出來酱鸭,又要跳進(jìn)mountComponent這個(gè)坑

image

組件掛載我這里不會(huì)展開詳解,盡量把重心放在生命周期方面垛吗,有興趣的朋友可以自行了解凹髓,或者看我底下的鏈接

beforeMount

當(dāng)組件執(zhí)行$mount并且擁有掛載點(diǎn)和渲染函數(shù)的時(shí)候,就會(huì)觸發(fā)beforeMount的鉤子怯屉,準(zhǔn)備組件的掛載

渲染視圖的函數(shù)updateComponent

之后Vue會(huì)定義一個(gè)updateComponent函數(shù)蔚舀,這個(gè)函數(shù)是整個(gè)掛載的核心,它由2部分組成锨络,_render函數(shù)和_update函數(shù)

  • render函數(shù)最終會(huì)執(zhí)行之前在initRender定義的createElement函數(shù)赌躺,作用是創(chuàng)建vnode
  • update函數(shù)會(huì)將上面的render函數(shù)生成的vnode渲染成一個(gè)真實(shí)的DOM樹,并掛載到掛載點(diǎn)上

第一次執(zhí)行updateComponent會(huì)渲染出整個(gè)DOM樹羡儿,這個(gè)時(shí)候頁面就完整的被展現(xiàn)了

渲染watcher

然后會(huì)實(shí)例化一個(gè)"渲染watcher"礼患,將updateComponent作為回調(diào)函數(shù)傳入,內(nèi)部會(huì)立即執(zhí)行一次updateComponet函數(shù)

watcher顧名思義是用來觀察的掠归,渲染watcher簡(jiǎn)而言之缅叠,就是會(huì)觀察模版中依賴變量的是否變化來決定是否需要刷新頁面,而updateComponet就是一個(gè)用來更新頁面的函數(shù)拂到,所以將這個(gè)函數(shù)作為回調(diào)傳入痪署。對(duì)于模版中的響應(yīng)式變量(下圖中的變量a)內(nèi)部都會(huì)保存這個(gè)渲染watcher(因?yàn)檫@些變量都有可能修改視圖),一旦變量被修改了就會(huì)觸發(fā)setter兄旬,最后都會(huì)再次執(zhí)行updateComponent函數(shù)來刷新視圖

image

mounted

實(shí)例化渲染watcher渲染出頁面后會(huì)進(jìn)入一個(gè)判斷丧叽,這里要注意的是,只有根實(shí)例才會(huì)為true并且觸發(fā)mounted鉤子永罚,那組件實(shí)例什么時(shí)候觸發(fā)mounted鉤子呢荐糜?

這里先給出答案,在src/core/vdom/create-component.js的insert鉤子(組件專屬的vnode鉤子),同時(shí)Vue會(huì)聲明一個(gè)insertedVnodeQueue數(shù)組绪撵,保存所有的組件vnode瓢姻,每當(dāng)一個(gè)組件vnode被渲染成DOM節(jié)點(diǎn)就會(huì)往這個(gè)數(shù)組里添加一個(gè)vnode元素,當(dāng)組件全部渲染完畢后音诈,會(huì)以子=>父的順序依次觸發(fā)mounted鉤子(最先觸發(fā)最里層組件的mounted鉤子)幻碱。隨后再回到_init方法,最后觸發(fā)根實(shí)例的mounted鉤子细溅,具體為什么會(huì)這么做有興趣的同學(xué)可以再深入研究

image

至此所有的數(shù)據(jù)都被初始化褥傍,并且渲染出了DOM節(jié)點(diǎn),接下來會(huì)介紹組件更新和組件銷毀的過程

組件更新

回到mountComponent那張圖喇聊,在實(shí)例化渲染watcher的時(shí)候恍风,Vue會(huì)給渲染watcher傳入一個(gè)對(duì)象,對(duì)象包含了一個(gè)before方法,執(zhí)行before方法就會(huì)執(zhí)行beforeUpdate鉤子朋贬,那什么時(shí)候執(zhí)行這個(gè)方法呢凯楔?

一旦模版的依賴的變量發(fā)生了變化,說明即將改變視圖锦募,會(huì)觸發(fā)setter然后執(zhí)行渲染watcher的回調(diào)摆屯,即updateComponent刷新視圖,在執(zhí)行這個(gè)回調(diào)前御滩,Vue會(huì)查看是否有before這個(gè)方法鸥拧,如果有則會(huì)優(yōu)先執(zhí)行before,然后再執(zhí)行updateCompont刷新視圖

Vue會(huì)將所有的watcher放入一個(gè)隊(duì)列削解,flushSchedulerQueue會(huì)依次遍歷這些watcer富弦,而渲染watcher會(huì)有一個(gè)before方法,從而觸發(fā)beforeUpdate鉤子

image

然后當(dāng)所有的watcher都遍歷過之后氛驮,代表數(shù)據(jù)已經(jīng)更新完畢腕柜,并且視圖也刷新了,此時(shí)會(huì)調(diào)用callUpdatedHooks矫废,執(zhí)行updated鉤子

組件銷毀

組件銷毀的前提是發(fā)生了視圖更新盏缤,Vue會(huì)判斷生成新視圖的vnode和舊視圖對(duì)應(yīng)的vnode的區(qū)別,然后刪除那些視圖中不需要渲染的節(jié)點(diǎn)蓖扑,這個(gè)過程最終會(huì)調(diào)用實(shí)例的$destroy方法唉铜,對(duì)應(yīng)源代碼的src/core/instance/lifecycle.js

image

依次按照順序執(zhí)行:

  1. 首先會(huì)直接執(zhí)行beforeDestory的鉤子,表示準(zhǔn)備開始銷毀節(jié)點(diǎn)律杠,此時(shí)是可以和當(dāng)前組件實(shí)例交互的最后時(shí)機(jī)
  2. 隨后會(huì)找到當(dāng)前組件的父節(jié)點(diǎn)潭流,從父節(jié)點(diǎn)的children屬性中刪除當(dāng)前的節(jié)點(diǎn)
  3. 對(duì)渲染watcher進(jìn)行注銷(vm._watcher存放的是每個(gè)組件唯一的渲染watcher)
  4. 對(duì)其他的watcher進(jìn)行注銷(user watcher,computed watcher)
  5. 清除這個(gè)實(shí)例渲染出的DOM節(jié)點(diǎn)
  6. 執(zhí)行destroyed鉤子
  7. 注銷所有的監(jiān)聽事件($off不傳參數(shù)會(huì)清空所有的監(jiān)聽事件)

總結(jié)

至此整個(gè)Vue的生命周期結(jié)束了,最后再總結(jié)一下每個(gè)生命周期主要都做了什么事情柜去,嚴(yán)格按照Vue內(nèi)部的執(zhí)行順序羅列

  • beforeCreate:將開發(fā)者定義的配置項(xiàng)和Vue內(nèi)部的配置項(xiàng)進(jìn)行合并灰嫉,初始化組件的自定義事件,定義createElement函數(shù)/初始化插槽
  • created:初始化inject嗓奢,初始化所有數(shù)據(jù)(props -> methods -> data -> computed -> watch)讼撒,初始化provide
  • beforeMount:尋找是否有掛載的節(jié)點(diǎn),根據(jù)render函數(shù)準(zhǔn)備開始渲染頁面/實(shí)例化渲染watcher
  • mounted:頁面渲染完成
  • beforeUpdate:渲染watcher依賴的變量發(fā)生變化股耽,準(zhǔn)備更新視圖
  • updated:視圖和數(shù)據(jù)全部更新完畢
  • beforeDestroy:注銷watcher根盒,刪除DOM節(jié)點(diǎn)
  • destroyed:注銷所有監(jiān)聽事件

事實(shí)上要想完全了解Vue的生命周期,還需要了解其他方面的知識(shí)點(diǎn)物蝙,例如組件掛載炎滞,響應(yīng)式原理,另外可能還需要了解一下Vue的編譯原理茬末,每個(gè)知識(shí)點(diǎn)又可以展開十幾個(gè)小的知識(shí)點(diǎn),但是當(dāng)你能夠真正理解Vue.js的核心原理,我相信對(duì)個(gè)人成長(zhǎng)來說是一個(gè)不小的收獲(終于寫完了脖子都酸了:(′°ω°`」 ∠):

砥礪前行 未來可期

參考資料

Vue.js 技術(shù)揭秘

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末丽惭,一起剝皮案震驚了整個(gè)濱河市击奶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌责掏,老刑警劉巖柜砾,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異换衬,居然都是意外死亡痰驱,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門瞳浦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來担映,“玉大人,你說我怎么就攤上這事叫潦∮辏” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵矗蕊,是天一觀的道長(zhǎng)短蜕。 經(jīng)常有香客問我,道長(zhǎng)傻咖,這世上最難降的妖魔是什么朋魔? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮卿操,結(jié)果婚禮上警检,老公的妹妹穿的比我還像新娘。我一直安慰自己硬纤,他們只是感情好解滓,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著筝家,像睡著了一般洼裤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上溪王,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天腮鞍,我揣著相機(jī)與錄音,去河邊找鬼莹菱。 笑死移国,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的道伟。 我是一名探鬼主播迹缀,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼使碾,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了祝懂?” 一聲冷哼從身側(cè)響起票摇,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎砚蓬,沒想到半個(gè)月后矢门,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灰蛙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年祟剔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摩梧。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡物延,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出障本,到底是詐尸還是另有隱情教届,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布驾霜,位于F島的核電站案训,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏粪糙。R本人自食惡果不足惜强霎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蓉冈。 院中可真熱鬧城舞,春花似錦、人聲如沸寞酿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伐弹。三九已至拉馋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惨好,已是汗流浹背煌茴。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留日川,地道東北人蔓腐。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像龄句,于是被迫代替她去往敵國和親回论。 傳聞我的和親對(duì)象是個(gè)殘疾皇子散罕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容