Vue生命周期總結


  每個Vue實例在被創建之前都要經過一系列的初始化過程,這個過程就是vue的生命周期。

  首先貼一張Vue文檔給出的生命周期圖示,並添加了一些注釋:

  Vue2.0的生命周期鈎子一共有10個,同樣結合官方文檔作出了下表

生命周期鈎子 詳細
beforeCreate 在實例初始化之后,數據觀測(data observer) 和 event/watcher 事件配置之前被調用。
created 實例已經創建完成之后被調用。在這一步,實例已完成以下的配置:數據觀測(data observer),屬性和方法的運算, watch/event 事件回調。然而,掛載階段還沒開始,$el 屬性目前不可見。
beforeMount 在掛載開始之前被調用:相關的 render 函數首次被調用。
mounted el 被新創建的 vm.$el 替換,並掛載到實例上去之后調用該鈎子。如果 root 實例掛載了一個文檔內元素,當 mounted 被調用時 vm.$el 也在文檔內。
beforeUpdate 數據更新時調用,發生在虛擬 DOM 重新渲染和打補丁之前。你可以在這個鈎子中進一步地更改狀態,這不會觸發附加的重渲染過程。
updated 由於數據更改導致的虛擬 DOM 重新渲染和打補丁,在這之后會調用該鈎子。當這個鈎子被調用時,組件 DOM 已經更新,所以你現在可以執行依賴於 DOM 的操作。
activated keep-alive 組件激活時調用。
deactivated keep-alive 組件停用時調用。
beforeDestroy 實例銷毀之前調用。在這一步,實例仍然完全可用。
destroyed Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。

  (除了beforeCreate和created鈎子之外,其他鈎子均在服務器端渲染期間不被調用。)

一、實際操作

  我們來可視化的觀察一下生命周期鈎子函數執行時狀態變化的情況

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <p>{{message}}</p>
    <keep-alive>
        <my-components msg="hello" v-if="show"></my-components>
    </keep-alive>
</div>
</body>
<script>
    var child = { template: '<div>from child: {{msg}}</div>', props: ['msg'], data: function () { return { childMsg: 'child' }; }, deactivated: function () { console.log('component deactivated!'); }, activated: function () { console.log('component activated'); } }; var app = new Vue({ el: '#app', data: function () { return { message: 'father', show: true }; }, beforeCreate: function () { console.group('beforeCreate 創建前狀態===============》'); var state = { 'el': this.$el, 'data': this.$data, 'message': this.message } console.log(state); }, created: function () { console.group('created 創建完畢狀態===============》'); var state = { 'el': this.$el, 'data': this.$data, 'message': this.message } console.log(state); }, beforeMount: function () { console.group('beforeMount 掛載前狀態===============》'); var state = { 'el': this.$el, 'data': this.$data, 'message': this.message } console.log(this.$el); console.log(state); }, mounted: function () { console.group('mounted 掛載結束狀態===============》'); var state = { 'el': this.$el, 'data': this.$data, 'message': this.message } console.log(this.$el); console.log(state); }, beforeUpdate: function () { console.group('beforeUpdate 更新前狀態===============》'); var state = { 'el': this.$el, 'data': this.$data, 'message': this.message } console.log(this.$el); console.log(state); console.log('beforeUpdate == ' + document.getElementsByTagName('p')[0].innerHTML); }, updated: function () { console.group('updated 更新完成狀態===============》'); var state = { 'el': this.$el, 'data': this.$data, 'message': this.message } console.log(this.$el); console.log(state); console.log('updated == ' + document.getElementsByTagName('p')[0].innerHTML); }, beforeDestroy: function () { console.group('beforeDestroy 銷毀前狀態===============》'); var state = { 'el': this.$el, 'data': this.$data, 'message': this.message } console.log(this.$el); console.log(state); }, destroyed: function () { console.group('destroyed 銷毀完成狀態===============》'); var state = { 'el': this.$el, 'data': this.$data, 'message': this.message } console.log(this.$el); console.log(state); }, components: { 'my-components': child } }); </script>
</html>

  首先來梳理一下結構:

  (1)我們創建了一個Vue根實例命名為app,將其掛載到頁面id為app的dom元素上。

  (2)局部注冊的一個組件child並在根實例中將其注冊使其可以在根實例的作用域中使用。

  (3)將子組件用<keep-alive> 包裹,為接下來的測試作准備。在谷歌瀏覽器打開開發者工具,開始測試!

1、create 和 mounted 相關

  根據打印結果:

  1、beforeCreate執行時:data和el均未初始化,值為undefined

  2、created執行時:Vue 實例觀察的數據對象data已經配置好,已經可以得到app.message的值,但Vue 實例使用的根 DOM 元素el還未初始化

  3、beforeMount執行時:data和el均已經初始化,但從{{message}}等現象可以看出此時el並沒有渲染進數據el的值為“虛擬”的元素節點

  4、mounted執行時:此時el已經渲染完成並掛載到實例

  beforecreated:el 和 data 並未初始化 ;created:完成了 data 數據的初始化,el沒有;beforeMount:完成了 el 和 data 初始化 ;mounted :完成掛載。(注意:在beforeMount階段應用的 Virtual DOM(虛擬Dom)技術,先把坑占住了,到后面mounted掛載的時候再把值渲染進去。)

2、activated 和 destroyed相關

  在前面的測試圖中,我們發現了activated周期鈎子已經被觸發,這是因為子組件my-components被<keep-alive> 包裹,隨el的掛載觸發。

  現在我們將此組件停用進行測試:由於子組件具有一個v-if指令v-if="show",因此我們可以通過將show的值置為false將其銷毀。控制台輸入 app.show = false;測試結果如下:

  由於在這里我們修改了data的值,所以會觸發beforeUpdate和updated鈎子,這里先不討論這一組鈎子,我們看到deactivated鈎子已經觸發,表示<keep-alive>已經停用,符合預期結果。

  現在我們對Vue實例進行銷毀,調用app.$destroy()方法即可將其銷毀,控制台測試如下:

 

  我們發現實例依然存在,但是此時變化已經發生在了其他地方,根據官方文檔描述:Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀

 

  這里我們將data中的message屬性改成了'message',發現dom並沒有進行相應的響應,這證實了之前的說法。同樣,如果你在子組件也加入destroyed鈎子,發現該鈎子也會被觸發,這也證明了子實例也會被一起銷毀。這里的銷毀並不指代'抹去',而是表示'解綁'。

 3、updated相關

  beforeUpdate和updated是最后一對周期鈎子了。

  我們發現beforeUpdate和updated觸發時,el中的數據都已經渲染完成,但根據beforeUpdate == father而updated == message可知,只有updated鈎子被調用時候,組件dom才被更新。

  在beforeUpdate可以監聽到data的變化,但是view層沒有被重新渲染,view層的數據沒有變化。等到updated的時候,view層才被重新渲染,數據更新。

二、一些應用的想法

  1、在created鈎子中可以對data數據進行操作,這個時候可以進行ajax請求將返回的數據賦給data

  2、在mounted鈎子對掛載的dom進行操作

  3、在使用vue-router時有時需要使用<keep-alive></keep-alive>來緩存組件狀態,這個時候created鈎子就不會被重復調用了,如果我們的子組件需要在每次加載的時候進行某些操作,可以使用activated鈎子觸發。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM