對於剛接觸vue一兩個月、才僅僅獨立作過一兩個vue項目的小白來講,之前一直自我感受本身知道vue的生命週期,html
直到前兩天去面試,面試官讓我說一下vue的生命週期。。。vue
其實個人心中是有那張圖的,可是由於學習、分析的年代久遠,心中有圖殊不知道怎麼表述,成了個能發聲的啞吧,react
最後也就只能按順序說出了那幾個鉤子函數,真是憋足了氣!面試
直到今天一氣呵成二刷生命週期,我才恍然大悟,原來我以前的理解中,潛意識裏一直是把那幾個鉤子函數當作了vue的生命週期!ajax
簡直了,想一想那天,面試官確定在內心把我鄙視死了吧!編程
好了不扯了,直接說我今天看完後,自我感受還很好的新的理解吧。api
也許往後再深刻接觸後,會發現今天的理解也很淺顯,可是至少今天比我前天好多了哈哈。app
生命週期:就是從一個組件或者實例開始被初始化、建立開始到這個實例被銷燬或者結束的一個過程。dom
這個過程好比官網表述的:在過程當中須要設置數據監聽、編譯模板、將實例掛載到 DOM 並在數據變化時更新 DOM 等ide
同時,在這個過程當中vue給咱們提供了不少的方法,也就是所說的生命週期鉤子函數。
在實例生命週期的不一樣階段藉助這些鉤子函數,「用戶在不一樣階段添加本身的代碼」
由此:真正的生命週期是一個流程,而不是單單那幾個鉤子函數,鉤子函數只是用來在流程的不一樣階段幫助咱們作更多的事情。
在我粗淺的理解下,我暫時把vue的生命週期統分紅五大區塊(我的的劃分)
1、建立(初始化)
2、查找與處理(找到組件並渲染)
3、掛載(插入)
4、更新(從新渲染並插入)
5、銷燬(卸載全部)
其中每一大塊又分幾個小的步驟,可是大致規律又是一模一樣:
好像都是廢話哈哈,但我真的對這一點的感覺很深入。
接下來一個一個來
就像咱們人從生下來到死這麼一個過程,要有這個流程,先得開始:
1、建立部分
new Vue( 這句代碼,初始化一個vue實例,開始建立一個vue對象
生命週期開始,init event初始化事件,爲當前實例作基礎配置;
建立以前,這裏提供一個鉤子函數,beforeCreate 開始建立鉤子,
這個時候還啥也沒作呢,頁面一片空白,能夠在頁面中先展現一個loading組件,給用戶一個友好體驗;
建立中,init injections(初始化註冊) & reactivity 建立過程當中,data屬性被成功綁定,dom未生成;
建立以後,這裏提供一個鉤子函數,created 建立完畢鉤子,
這個時候vue對象實例化完畢,dom樹依舊未生成,頁面仍是一片空白,
可是,實例已完成如下的配置:數據觀測 (data observer),屬性和方法的運算,watch/event 事件回調。
能夠在這裏ajax獲取數據賦給data屬性了,以便往後使用;
2、查找部分
也就是new Vue()括號裏邊的參數開始被執行解析的過程:
new Vue({ el: '#app', router, store, template: '<App/>', components: { App } })
或
new Vue({ render (h) { return h('div', this.hi) } })
查找el屬性的對應內容,el對應的DOM 元素做爲 Vue 實例的掛載目標
若是值能夠被找到,那麼實例將當即進入編譯過程
若是找不到,就去查是否在括號後邊掛載了$.mount()並有內容,用於手動開啓編譯
以上官網解說:「若是在實例化時存在el這個選項,實例將當即進入編譯過程,不然,須要顯式調用 vm.$mount()
手動開啓編譯。」
官網:https://cn.vuejs.org/v2/api/#%E9%80%89%E9%A1%B9-DOM
若是都沒找到,生命週期結束;
若是順利的都找到了,就繼續往下查找{}內的下一個屬性template
若是template對應的值當中有組件或者有html內容,那麼也算查找成功,
若是爲空,繼續查找render屬性值是否爲空
緊接着,若是{}選項中存在渲染函數render,
那麼template將被忽略,由於render渲染函數是字符串模板的代替方案,
render可讓你發揮 JavaScript 最大的編程能力,而不用寫template的靜態模板
若是沒有或爲空,template字符串模板將會替換掛載的元素,即el的屬性值
掛載元素el的內容都將被忽略,除非模板template的內容有分發插槽。
若是template和render都不存在,則生命週期結束。
查找階段彙總:
Vue 選項中的 render
函數若存在,則 Vue 構造函數不會從 template
選項或經過 el
選項指定的掛載元素中提取出的 HTML 模板編譯渲染函數。
至此,食材都準備好了,vue大廚開始開工吧!
此時,將template裏的內容放到render函數中開始渲染處理,即執行render方法渲染template裏的內容。
(這裏是對vue的語法進行解析嗎?)
題外話:
el其實就是往後要掛載vue組件的一個目標點,若是連目標都找不到,還活着幹嗎,乾脆結束
template/render就是往後要作的事情,若是都不知道本身接下來要去作什麼,還活着幹嗎,乾脆也結束
作人,又未嘗不是如此。
菜都準備好了總要上桌吧!
全部的dom結構都被渲染好了,vue語法也被解析成正常的html內容了,總要放到頁面展現了吧:
3、掛載部分
開始掛載以前,這裏提供一個鉤子函數,beforeMount掛載前鉤子,
編譯template裏的內容並在虛擬dom中執行,頁面上依舊沒有任何展現;
掛載中,要作的事就是建立vm$.el,並替換到el元素,
這一段我也不是太理解,大概感受就是將#app的那段空的div換成剛纔vue生成好的虛擬dom;
掛載完畢,這裏提供一個鉤子函數,mounted掛載完畢鉤子,
el
被新建立的 vm.$el
替換,並掛載到實例上去
至此,全部的dom結構和數據都被展現到頁面當中,
這時能夠作一些事情,好比關掉以前展現的loading;
注意: mounted
不會承諾全部的子組件也都一塊兒被掛載。若是你但願等到整個視圖都渲染完畢,能夠用 vm.$nextTick 替換掉 mounted
mounted: function () { this.$nextTick(function () { // Code that will run only after the // entire view has been rendered }) }
nextTick: 在dom結構更新後使用這個方法獲取最新的dom結構
生命週期到這裏,也算初步完成了他的使命,
若是是一個純靜態頁不作任何修改展現的話,根本不必用到生命週期的後兩區塊內容了。
可是若是在mounted以後再對實例中的data屬性作操做的話,就會走進生命週期的另外一個階段:更新
4、更新部分
依舊是那個套路,觸發了更新的開關後,會給一個開始更新的回調:
更新以前,這裏有一個鉤子函數,beforeUpdate開始更新前鉤子,
在這個鉤子裏能夠提供一個彈窗提示用戶確認跟新啥的。或者再展現一個loading;
也能夠手動移除已添加的事件監聽器
更新中,vue實例要開始將舊數據替換爲新數據,在虛擬dom中從新渲染,
虛擬dom開始改變,可是頁面這時沒有任何變化,由於只是改的虛擬dom,還並未真正修改dom結構;
更新完畢,這裏有一個鉤子函數,updated更新後鉤子,
這時真正的dom結構被完全替換,頁面展現上也會發生改變,
在這個鉤子裏能夠提供一個彈窗告訴用戶更新完畢。同時去掉loading彈層啥的;
注意: updated
不會承諾全部的子組件也都一塊兒被重繪。若是你但願等到整個視圖都重繪完畢,能夠用 vm.$nextTick 替換掉 updated
:
updated: function () { this.$nextTick(function () { // Code that will run only after the // entire view has been re-rendered }) }
若是執行了vm.$destory,就會進入到最後一個部分
5、銷燬部分
同上
開始銷燬vue實例以前,會有一個鉤子函數提示開發者組件要開始銷燬:beforeDestory開始銷燬鉤子,
在這個鉤子中咱們能夠提醒用戶是否刪除等,或者作一些開發者與業務有關的相關操做;
銷燬中,vue這時的主要目標就是卸載,就像人要洗澡前各類脫同樣(具體就不要想象了!),
他要卸載在身上的各類監聽、各類事件, 各類綁定以及各類子組件實例銷燬,感受像毀滅一切
好比watchers(我沒用過沒有發言權)、子組件child components、事件event;
銷燬後,這時再次提供最後一個鉤子函數,destoryed銷燬完畢,
在這裏咱們能夠提示用戶刪除完畢啥的,也能夠清空咱們本身的定時器或者作一些其餘善後工做;
到這一步,這次整個vue實例的生命週期就完全結束了。
以上,僅是本身瞭解vue後再刷生命週期圖的二次理解,僅表明我的的理解,
不必定徹底正確,歡迎指正,最後也別全信。畢竟絕知此事要躬行。
最後,貼一張一刷時本身備註的官網生命週期圖,對照着圖再去理解個人總結應該更好。(查看清晰大圖:右鍵新標籤頁打開)
哇塞,認真學習了16分鐘,記錄草稿後,加上本身理解對樹講述了兩遍後,一口氣2000字的心得寫下來了。
真的是畫竹要先成竹在胸才行!
2018-06-09 14:07:16