初探 Vue 生命週期和鉤子函數

生命週期

生命週期函數就是 Vue 實例在某一個時間點會自動執行的函數。vue

簡單來講就是好像把人的出生到死亡分紅一個個階段,你取名字確定是在你出生階段,而不是在成年階段;你結婚確定是在成年階段,而不是在出生階段;若是說你在出生階段想去階段,那確定是不行的。
組件也是同樣,在實例化的時特定階段調用特定方法,調用的這個方法就是鉤子函數。segmentfault

鉤子函數

鉤子函數和回調函數有什麼區別嗎?後端

它們區別是:app

js派函數監聽事件 => 監聽函數就是所謂的鉤子函數 => 函數鉤取事件:函數主動找事件 => 鉤子函數

js預留函數給dom事件,dom事件調用js預留的函數 => 事件派發給函數:事件調用函數 => 回調函數dom

打個比方:異步

鉤子函數:一個房間裏的監控攝像頭監控着每個進入的人的面部特徵,識別出了符合條件的人就觸發警告(執行函數事件);

回調函數:能夠看作是在一片地區埋了許許多多的地雷,一旦踩中了某個地雷(觸發事件),地雷就會爆炸(執行函數事件)。函數

能夠簡單的理解爲:post

鉤子函數是事件被動的監聽,一旦條件觸發就執行

回調函數是主動事件,執行函數體內容動畫

生命週期探究

<template>
    <div>{{msg}}</div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'hello world',
      msg1: ''
    }
  },
  beforeCreate () {
    console.groupCollapsed('beforeCreate 建立前狀態')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  created () {
    console.groupCollapsed('created 建立前狀態')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data.msg)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  beforeMount () {
    console.groupCollapsed('beforeMount 掛載前狀態')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data.msg)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  mounted () {
    console.groupCollapsed('mounted 掛載後狀態')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data.msg)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
    setTimeout(() => {
      this.$data.msg = '123'
    }, 5000)
  },
  activated () {
    console.groupCollapsed('activated 掛載後狀態')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(this.$data.msg)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
    setTimeout(() => {
      this.$data.msg = 'hello tiantian'
    }, 10000)
  },
  beforeUpdate () {
    console.groupCollapsed('beforeUpdate 更新前狀態')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(document.getElementById('app').innerHTML)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  updated () {
    console.groupCollapsed('updated 更新後狀態')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(document.getElementById('app').innerHTML)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
    setTimeout(() => {
      this.$destroy()
    }, 5000)
  },
  beforeDestroy () {
    console.groupCollapsed('beforeDestroy 實例銷燬前狀態')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(document.getElementById('app').innerHTML)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  },
  destroyed () {
    console.groupCollapsed('destroyed 實例銷燬後狀態')
    console.log('%c%s', 'color:MediumVioletRed', 'el     : ' + this.$el)
    console.log(this.$el)
    console.log('%c%s', 'color:MediumVioletRed', 'data   : ' + this.$data)
    console.log(document.getElementById('app').innerHTML)
    console.log('%c%s', 'color:MediumVioletRed', 'msg: ' + this.msg)
    console.groupEnd()
  }
}
</script>

beforeCreatecreated

beforeCreate:在實例初始化完成時,被執行

created:在初始化結束以後會再初始化一些外部注入和一些雙向綁定相關的事情時,被執行this

這兩個鉤子函數執行完以後,初始化基本完成了。

beforeCreate階段,eldata都沒有被掛載;而在created階段,el還沒被掛在,但data已經被掛載了,以下圖所示:

這裏el爲啥沒有被掛載呢?

看上圖,在created執行完畢後,它會詢問一個條件:你這個Vue實例裏是否有el這個選項。

若是有就又會詢問是否有template這個選項:

  • 若是沒有template就會走右側的分支,

    • 若是這個實例沒有template,就會將el這個根節點當作模版,來進行渲染
  • 若是有template就會走左側的分支

    • template做爲模版去渲染

beforeMountmounted

beforeMount:執行時,頁面尚未被渲染
mounted:執行時,頁面已經被渲染了

從圖中也能夠看出,在beforeMount執行時,el尚未被掛在;當mounted執行時,el被掛載到頁面了。

beforeUpdateupdated

beforeUpdate:數據被改變,還沒渲染以前會被執行

updated:數據被改變,渲染完成後會被執行

這張圖中有個奇怪的現象,爲何在beforeUpdateupdated兩個鉤子函數中,elmsg都是同樣呢?beforeUpdate執行是不該該是老數據嘛,怎麼這裏也是最新的數據了?

由於這裏的el是虛擬dom,不是真實的dom,和data都是對象,在加上console.log這裏是個異步操做,當你點開console.log時,其實代碼早就跑完了,數據已是最新的了,因此就會看到在這兩個函數中輸出結果是同樣的了。

能夠用document.getElementById('app').innerHTML獲取真實的Dom結構,這時咱們就能夠看到這兩處不同的地方了。

beforeDestroydestroyed

調用vm.$destroy()方法可對實例銷燬

beforeDestroy:實例被銷燬前被執行

destroyed:實例被銷燬後被執行

activateddeactivated

使用keep-alive標籤後,會有兩個生命週期函數分別是:activateddeactivated

activated:頁面展現的時候被執行

deactivated:頁面被隱藏或者頁面即將被替換成新的頁面時被執行

總結

created:掛載以前須要作的一些事情能夠在放在這裏面,好比頁面加載時loading動畫

mounted:向後端發請求,能夠放在這個函數中。

這兩個鉤子函數使用時機重疊部分不少,反正是怎麼方便怎麼來就是了。

參考資源

  1. Vue2.0 探索之路——生命週期和鉤子函數的一些理解
  2. vue2 爲何beforeUpdate時的$el 和$data與updated時的同樣
  3. JavaScript:鉤子函數與回調函數的區別
相關文章
相關標籤/搜索