Vue中生命週期的理解

vue生命週期

生命週期能夠分爲四個階段,初始化階段,模板編譯階段,掛載階段,已掛載和卸載階段。html

  •   el :選擇器
  •   $el:對應選擇器的template模板(html代碼)
  •   render:也是vue實例中的一項,其參數更接近vue解析器,按優先級,render參數 > vue實例對象中有template > 外部的HTML模板 後面兩個也是將其編譯成render函數;【注意】render選項參數比template更接近Vue解析器!因此優先級以下:

     render函數選項  > template參數  > 外部HTMLvue

  •   $mount :當Vue實例沒有el屬性時,則該實例尚沒有掛載到某個dom中,假如須要延遲掛載,能夠在以後手動調用vm.$mount()方法來掛載。例如:

         new Vue({內部無el項}).$mount('#app')是延遲加載,同下面的語句相同ajax

         new Vue({el:"#app",***})算法

  1. computed計算屬性可用於快速計算視圖(View)中顯示的屬性。這些計算將被緩存,而且只在須要時更新.
  2. watch主要用於監控vue實例的變化,它監控的變量固然必須在data裏面聲明才能夠,它能夠監控一個變量,也能夠是一個對象,通常用於監控路由、input輸入框的值特殊處理等等,它比較適合的場景是一個數據影響多個數據.
  3. methods每當觸發從新渲染時,方法的調用方式將老是再次執行函數。所以,函數必須是一個純函數。它不能有反作用。輸出只能依賴於傳遞給函數的值。

HTML

<div id="app">
    <p>{{ message }}</p>
    <h1>{{message + '這是在outer HTML中的'}}</h1>
</div>

js

var app = new Vue({
    el: '#app',
    data: {
        message : "xuxiao is boy"
    },
    template:"<h1>{{message +'這是在template中的'}}</h1>",
    // render: function(createElement) {
    //     return createElement('h1', 'this is createElement')
    // }
})

最終結果

20190520142852951.png
20190520142920131.png
20190520142946922.png

vue整個過程作了些什麼

new Vue()建立實例

  1. vue項目都是經過組件化進行實現的,一個頁面經過若干組件組成,構成一個組件樹,
  2. 每個組件都經過一個vue實例來進行管理,
  3. 每當要渲染一個組件前,都會爲該組件建立一個vue實例來管理組件中的數據和事件方法。
  4. 經過new Vue()建立實例時,實際建立了一個vue實例的空殼,初始化生命週期和事件
注意:這時候實例中的data選項尚未數據,因此在beforecreated中沒法訪問到data中的數據

初始化階段

beforecreate

  1. 在這個階段,完成實例初始化,
  2. 初始化非響應式變量 this指向建立的實例;
  3. 能夠在這加個loading事件;
  4. data computed watch methods上的方法和數據均不能訪問,這個時候的Vue實例還什麼都沒有,
  5. $route對象是存在的,能夠根據路由信息進行重定向之類的操做;
  6. 這個階段的data對象未完成初始化,el也沒有完成初始化;
  7. DOM尚未開始
注意:在beforecreated中千萬不要去修改data中賦值的數據,最先也要在create裏面去作(添加一些行爲)

created 【建立完成】

在模板渲染成HTML前調用,即一般初始化一些屬性值,而後再渲染成視圖, 未掛載DOM;created時還沒完成掛載,沒法經過id等得到DOM元素;vue-router

  1. 實例建立完成 完成數據(data props computed)的初始化 導入依賴項。
  2. 可訪問data computed watch methods上的方法和數據 ;
  3. 不能訪問el【初始化還未完成】,ref爲空數組 ;不能對元素進行操做;
  4. 可在這結束loading,
  5. 還作一些初始化,實現函數自執行,
  6. 能夠對data數據進行操做,可進行一些請求,請求不易過多,避免白屏時間太長。
  7. el仍是undefined,
  8. 而數據已經與data中的屬性進行綁定(放在data中屬性當值發生改變的同時,視圖也會發生變化),
  9. 在這裏能夠在渲染前倒數第二次更改數據的機會,不會觸發其餘的鉤子函數,通常能夠在這裏作初始數據的獲取
  10. 若在此階段進行的 DOM 操做必定要放在 Vue.nextTick() 的回調函數中;由於created() 鉤子函數執行的時候 DOM 其實並未進行任何渲染c#

    Vue.nextTick( [callback, context] ):在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。

模板編譯階段

beforemount & mount

在created後,beforemount前,會檢查el選項,沒有就會調用vm.$mount(),而後就會繼續檢查template,沒有的話就綁定el選項的html,進入beforemount後,編譯模板爲虛擬的DOM,,開始render,將虛擬DOM渲染到頁面上;後端

從created到beforeMount的過程當中,數組

var app = new Vue({
            el: '#app',
            data: {
                message : "xuxiao is boy"
            },
            template:"<h1>{{message +'這是在template中的'}}</h1>",
            // render: function(createElement) {
            //     return createElement('h1', 'this is createElement')
            // },

首先會判斷vue實例中有沒有el選項,若是有的話則進行下面的編譯,可是若是沒有el選項,則中止生命週期,直到vue實例上調用vm.$mount(el)。緩存

若是有el,再判斷是否有template參數,若是有,則把其看成模板編譯成render函數,
20190520143735512.pngapp

若是沒有,則把外部的html做爲模板編譯。template中的模板優先級高於outer HTML模板。

20190520143925157.png
這是把outerHTML看成模板編譯了

<div id="app">

<p>{{ message }}</p>
<h1>{{message + '這是在outer HTML中的'}}</h1>

</div>

若是把實例中render function選項的註釋去掉,則直接用render function裏的,獲得網頁以下

2019052014420087.png

因此按優先級來講 render function>template>outerHTML
————————————————

在vue對象中還有一個render函數,它是以createElement做爲參數,而後作渲染操做,並且咱們能夠直接嵌入JSX.
綜合排名優先級:render函數選項 > template選項 > outer HTML.

掛載階段

beforeMount【掛載以前】

在這個階段,$el還只是咱們在HTML裏面寫的節點。$el屬性已存在,是虛擬dom,只是數據未掛載到模板中;有了el,編譯了template|/outerHTML 能找到對應的template,並編譯成render函數

  1. 載入前(完成了data和el數據初始化),
  2. 可是頁面中的內容仍是vue中的佔位符
  3. $el屬性已存在,是虛擬dom,只是數據未掛載到模板中。
  4. data中的message信息沒有被掛在到Bom節點中,
  5. 在這裏能夠在渲染前最後一次更改數據的機會,不會觸發其餘的鉤子函數,通常能夠在這裏作初始數據的獲取

mounted 【成功掛載】

完成建立vm,

完成el的雙向綁定,完成掛載dom和渲染,能夠在這個階段對掛載的DOM進行操做;

ref 可在這發起後端請求,拿回數據,配合路由鉤子作一些事情; 可對DOM 進行操做

載入後html已經渲染(ajax請求能夠放在這個函數中),把vue實例中的data裏的message掛載到BOM節點中去

beforeUpdate

更新前狀態(view層的數據變化前,不是data中的數據改變前),從新渲染以前觸發,而後vue的虛擬dom機制會從新構建虛擬dom與上一次的虛擬dom樹利用diff算法進行對比以後從新渲染

  • 只有view上面的數據變化纔會觸發beforeUpdate和updated,僅屬於data中的數據改變是並不能觸發;
  • 數據更新以前 可在更新前訪問現有的DOM,如手動移除添加的事件監聽器;
  • beforeUpdate是指view層的數據變化前【具體的能夠用this.$el.innerHTML能夠看出沒有改變】,不是data中的數據改變前觸發。由於Vue是數據驅動的

updated

數據已經更改完成,dom也從新render完成【具體的能夠用this.$el.innerHTML能夠看出已經改變了

完成虛擬DOM的從新渲染和打補丁; 組件DOM 已完成更新; 可執行依賴的dom 操做 注意:不要在此函數中操做數據,會陷入死循環的。

當這個鉤子被調用時,組件 DOM 已經更新,因此你如今能夠執行依賴於 DOM 的操做。然而在大多數狀況下,你應該避免在此期間更改狀態。若是要相應狀態改變,一般最好使用計算屬性或 watcher取而代之。

view層的數據更新後,data中的數據同beforeUpdate,都是更新完之後的。

注意:會發現beforeUpdateupdated鉤子函數中的$el同樣,根據官方理解beforeUpdate應該指向虛擬dom,因此纔會同樣,而dom中的真正內容不同,可是beforeMountmouted鉤子函數中爲何又會有區別呢?感受是設計的不足之處。**_

activated

  • 在使用vue-router時有時須要使用來緩存組件狀態,這個時候created鉤子就不會被重複調用了,
  • 若是咱們的子組件須要在每次加載的時候進行某些操做,可使用activated鉤子觸發

deactivated

keep-alive 組件被移除時使用

beforeDestroy

實例銷燬以前調用。在這一步,實例仍然徹底可用。
說明:

beforeDestroy(){
    console.group('beforeDestroy 銷燬前狀態==========>>');
    console.log("%c%s", "color:red", "el     : "+this.$el);   //[object HTMLDivElement]
    console.log(this.$el);
    console.log("%c%s", "color:red", "data   : "+this.$data); //[object Object]
    console.log("%c%s", "color:red", "message: "+this.message);   //今天週二了!!!
},

destroyed

官方解釋:Vue 實例銷燬後調用。調用後,Vue 實例指示的全部東西都會解綁定,全部的事件監聽器會被移除,全部的子實例也會被銷燬。

說明:執行destroy方法後,對data的改變不會再觸發周期函數,此時的vue實例已經解除了事件監聽以及和dom的綁定,可是dom結構依然存在。

destroyed(){
    console.group('destroyed 銷燬完成狀態==========>>');
    console.log("%c%s", "color:red", "el     : "+this.$el);   //[object HTMLDivElement]
    console.log(this.$el);
    console.log("%c%s", "color:red", "data   : "+this.$data); //[object Object]
    console.log("%c%s", "color:red", "message: "+this.message);   //今天週二了!!!
},

具體使用

  • beforeCreate:這個時候data,watcher,methods通通沒有,這個時候的Vue實例還什麼都沒有,可是$route對象是存在的,能夠根據路由信息進行重定向之類的操做。
  • 20190520144436609.png
  • 20190520144455848.png

mouted和created

20190520144542445.png

父子組件嵌套時觸發鉤子函數順序

加載渲染過程

  父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

子組件更新過程
  父beforeUpdate->子beforeUpdate->子updated->父updated

父組件更新過程
  父beforeUpdate->父updated

銷燬過程
  父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

總結

  • beforecreate:能夠在這加個loading事件
  • created :在這結束loading,還作一些初始化,實現函數自執行
  • mounted : 在這發起後端請求,拿回數據,配合路由鉤子作一些事情
  • beforeDestory: 你確認刪除vue實例了嗎?
  • destoryed :當前實例已被銷燬,解綁相關指令和事件監聽器

參考文章:
http://www.javashuo.com/article/p-qhbnffir-gw.html
http://www.javashuo.com/article/p-vbplkdch-hs.html
https://www.jianshu.com/p/7026b73bb626

相關文章
相關標籤/搜索