Vue生命週期

每一個 Vue 實例在被建立時都要通過一系列的初始化過程——例如,須要設置數據監聽、編譯模板、將實例掛載到 DOM 並在數據變化時更新DOM等。同時在這個過程當中也會運行一些叫作生命週期鉤子的函數,這給了用戶在不一樣階段添加本身的代碼的機會html

一個完整的vue生命週期會經歷如下鉤子函數

  • beforeCreate --- 建立前
  • created --- 建立完成
  • beforeMount --- 掛載前
  • mounted --- 掛載完成
  • beforeUpdate --- 更新前
  • updated --- 更新完成
  • beforeDestroy --- 銷燬前
  • destroyed --- 銷燬完成

各個鉤子函數在chrome控制檯下的打印狀況

下面逐步解讀各個鉤子函數的步驟vue

beforeCreate -> created

  • 初始化vue實例,進行數據觀測

created

  • 完成數據觀測,屬性與方法的運算,watch、event事件回調的配置
  • 可調用methods中的方法,訪問和修改data數據觸發響應式渲染dom,可經過computed和watch完成數據計算
  • 此時vm.$el 並無被建立
  • 通常在created中進行ajax請求

created -> beforeMount

  • 判斷是否存在el選項,若不存在則中止編譯,直到調用vm.$mount(el)纔會繼續編譯
  • 若存在el,則判斷是否存在template,若存在,則將template編譯成render函數;若不存在,則直接編譯el所對應的外部html
  • 若是存在render函數,則首先對其進行編譯
  • 此過程當中vm.el被實例化爲el選項對應DOM元素,因此在beforeMount中,用vm.el獲取到的是掛載DOM的HTML

優先級: render > template > outerHTMLajax

beforeMount

  • 在此階段可獲取到vm.el
  • 此階段vm.el雖已完成DOM初始化,但並未掛載在el選項上

beforeMount -> mounted

  • 此階段vm.el完成掛載,vm.$el生成的DOM替換了el選項所對應的DOM*

mounted

vm.el已完成DOM的掛載與渲染,此刻打印vm.$el,發現以前的掛載點及內容已被替換成新的DOM算法

經過實例驗證一下chrome

<div id="app">
    <h1 ref="h1" id="h1">{{message}}</h1>
    <button @click="changeMsg">change</button>
 </div>
 
 var vm = new Vue({
    el: '#app',
    data: {
      message: 'Vue的生命週期'
    },
    template: '<h2 id="h2">{{message}}</h2>',
    beforeMount: function() {
      console.group('------beforeMount 掛載前------');
      console.log(this.$el);
      console.log("%c%s", "color:red","data : " + this.$data); //已被初始化  
      console.log("%c%s", "color:red","message: " + this.message); //已被初始化  
      let h1 = document.getElementById('h1')
      let h2 = document.getElementById('h2')
      console.log('h1:',h1)
      console.log('h2:',h2)
    },
    mounted: function() {
      console.group('------mounted 掛載完成------');
      console.log(this.$el);
      console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
      console.log("%c%s", "color:red","message: " + this.message); //已被初始化 
      let h1 = document.getElementById('h1')
      let h2 = document.getElementById('h2')
      console.log('h1:',h1)
      console.log('h2:',h2)
    },
}
複製代碼

  • 可看出在掛載前,是以初始el與虛擬DOM存在的,template還未被編譯到,故h2打印出null
  • 而在掛載後,vm.$el完成了對el的替換,並完成了dom的渲染,因此h2打印出掛載渲染後的template,而el被替換,因此h1打印爲null

beforeUpdate

當渲染在模板上的data數據更新時,會觸發beforeUpdate方法bash

  • 更新的數據必須是被渲染在模板上的(el、template、render之一)
  • 此時view層還未更新
  • 只有在掛載完成後,才能夠觸發更新方法(由於掛載完成後才完成模板的渲染,而update則是對模板數據的更新與從新渲染)
  • 若在beforeUpdate中再次修改數據,不會再次觸發更新方法

updated

  • 完成view層的更新
  • 若在updated中再次修改數據,會再次觸發更新方法(beforeUpdate、updated)
  • 當數據變化後,經過render函數生成VNode,經過patchVNode對比先後變化,diff算法進行更新、添加、刪除等操做生成真實的DOM節點

正常更新操做app

beforeUpdate: function () {
    console.group('beforeUpdate 更新前===============》');
    console.log("%c%s", "color:red","message: " + this.message); 
    console.log(this.$refs.h1.innerHTML)
},
updated: function () {
    console.group('updated 更新完成===============》');
    console.log("%c%s", "color:red","message: " + this.message); 
    console.log(this.$refs.h1.innerHTML)
},
複製代碼

  • beforeUpdate中還未完成view層的更新,此階段打印出的innerHTML還是未修改前的數據
  • updated中完成了view層更新,打印的innerHTML爲修改後的數據
  • 不能直接輸出data數據,控制檯輸出的數據爲view層更新後的數據,可改成innerHTML驗證

在updated中修改數據dom

beforeUpdate: function () {
    console.group('beforeUpdate 更新前===============》');
    console.log("%c%s", "color:red","message: " + this.message); 
    console.log(this.$refs.h1.innerHTML)
},
updated: function () {
    console.group('updated 更新完成===============》');
    console.log("%c%s", "color:red","message: " + this.message); 
    console.log(this.$refs.h1.innerHTML)
    this.message = 'updated2'
},
複製代碼

  • 當updated完成數據的更新與view層的渲染後,若修改數據,則會再次觸發更新方法

beforeDestroy

  • 實例被銷燬前調用,此時實例仍可訪問

destroyed

  • 實例被銷燬後調用
  • 徹底銷燬一個實例。清理它與其它實例的鏈接,解綁它的所有指令及事件監聽器
  • Watcher對象從其所在Dep中釋放
  • 並不能清除DOM,僅僅銷燬實例

  • 當beforeDestroy時,實例未被銷燬,此時可經過this.$refs訪問到該DOM
  • 當destroyed後,實例被銷燬,此時經過this.$refs訪問爲null
相關文章
相關標籤/搜索