iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
0
Modern Web

Déjà-vu ? 要 Vue 過才知道系列 第 15

Vue 的實例與生命週期 Instance-life-cycles

是否世間萬物都有週期?那會一直輪週期的就叫做輪迴嗎?

說到 Vue 的生命週期,相信大家都看過這張圖:lifecycle

在 Vue 所使用到的整個生命週期方法,可以想像成是一齣戲要上演,哪一個主角需要在哪個時候上場、哪個配角需要在哪個時刻退場,都需要有邏輯才可以讓故事產生連貫性與流暢。

Vue 的生命週期方法雖然共有八個,但並不是每個都需要用到,就像在戲裡,有些橋段不出現、配角不出現也不會影響整齣性的故事性。

把 Vue 的生命週期分為三個大階段會比較容易理解:第一階段的「初始化顯示」、第二階段「更新狀態顯示」、第三階段「死亡、銷毀 Vue 實例」,每個階段都有對應的生命週期 callback 方法,這些生命週期的方法也稱為「生命週期鉤子」掛載在不同時期。 Vue 的生命週期比 React 還要複雜一些。

為了避免 this 的混淆,這些生命週期的方法都是回調方法(callback),所以最好一律都寫成箭頭函式,讓 this 直接指向父級。

Vue 的生命週期各階段都做了什麼?

0. 創建 Vue 的實例

當我們創建好一個 Vue 的實例,就會馬上進入下一個階段beforeCreate()

1. 初始化顯示階段

  • beforeCreate() 實例創建前

    • 準備工作:觀察初始化(Observe Data)、初始化事件(Init Events)
    • 這個階段實例的 data、methods 是讀不到的
  • created() 實例創建後

    • 這個階段已經完成了資料觀察初始化(data observer),屬性和方法的運算, watch/event 事件回調。mount 掛載階段還沒開始,$el 屬性目前不可見,資料並沒有在 DOM 元素上進行渲染。
  • beforeMount() 在掛載開始之前被調用

  • 相關的 render 函數首次被調用。

  • mounted()

  • 初始化顯示之後。立即調用,是最常用的 callback,用來「掛載」到頁面上。

  • el選項的 DOM 節點被新創建的 vm.$el 所替換,並掛載到實例上去之後調用此生命週期方法。此時實例的資料在 DOM 節點上進行渲染。

2. 更新狀態顯示階段

this.xxx = value

  • beforeUpdate() 資料更新時調用

    • 但不進行 DOM 重新渲染,在資料更新時 DOM 沒渲染前可以在這個生命方法裡進行狀態處理。
  • updated() 資料更新並且 DOM 重新渲染

    • 這個狀態下資料更新並且 DOM 重新渲染,當這個生命週期方法被調用時,組件 DOM 已經更新,所以這時可以執行依賴於 DOM 的操作。當實例每次進行資料更新時 updated 都會執行。

當我們調用 vm.$destroy()時,就會進入下一個銷毀 Vue 實例的階段

3.死亡、銷毀 Vue 實例階段

也稱死亡,也就是沒有互動的功能。

  • beforeDestory() 實例銷毀之前調用

  • destoryed() 實例銷毀後調用

    • Vue 實例銷毀後調用。調用後,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。

查看生命週期方法的順序範例

範例:一行字,每隔一秒會切換成隱藏。

在初始化之後,把初始化的值以v-show的方式讓<p>依定時器的規則顯示。
再設定一個按鈕,綁定可以銷毀 vm 的函式,當點擊按鈕時這個 vm 會銷毀而停止顯示或隱藏切換,這個定時器掛載到mounted()之後,點擊按鈕雖然會停止文字顯示的切換,卻不會停止我們在定時器裡放的console.log('++++++'),也表示「定時器」並沒有被銷毀。

要把整個定時器銷毀(進入銷毀 Vue 實例)階段,需要在beforeDestroy()這個階段清除定時器,我們可使用clearInterval()來清除定時器,但是如何找到我們要銷毀的定時器?可以在mounted()階段的定時器,指向我們設定的變數this.intervalId = setInterval()來讓清除定時器的函式找到。

在實例裡加入每個時期的生命週期方法,並用console.log印出來,執行一下頁面就可看到其順序。

常用的生命週期方法?

  • mounted():主要用來發送ajax請求,啟動定時器等非同步的任務。
  • beforeDestory():做收尾的工作,例如清除定時器,否則定時器會一直執行下去(如範例)
  • created():進行 ajax 請求異步數據的獲取、初始化數據
  • mounted():掛載元素內 dom 節點的獲取
  • nextTick():針對單一事件更新數據後立即操作 dom
  • updated():任何數據的更新,如果要做統一的業務邏輯處理
  • watch():監聽具體數據變化,並做相應的處理

實際操作

來 codepen 看看:VueJs Instance Lifecycle Hooks 生命週期鉤子,別忘了觀察 console 的變化。
HTML 部分:

<button @click="destroyVm">Destroy vm</button>
<p v-show="isShow">Hello Paris</p>

Vue 實例的部分

const vm = new Vue({
  el: '#app',
  data: {
    isShow: true,
  },
  // 1.初始化顯示階段
  beforeCreate() {
    console.log('1. beforeCreate');
  },
  created() {
    console.log('2. created');
  },
  beforeMount() {
    console.log('3. beforeMount');
  },
  // 初始化後的顯示,所以放在mounted(只用一次)
  mounted() {
    console.log('4. mounted');
    // 定時器,每一秒改變一次
    this.intervalId = setInterval(() => {
      console.log('+++++++++');
      this.isShow = !this.isShow;
    }, 1000);
  },
  // 2.更新狀態顯示階段
  beforeUpdate() {
    console.log('5. beforeUpdate');
  },
  updated() {
    console.log('6. updated');
  },
  // 3.死亡、銷毀 Vue 實例階段 / 銷毀之前調用(只用一次)
  beforeDestroy() {
    // 清除定時器
    clearInterval(this.intervalId);
    console.log('7. beforeDestroy');
  },
  destroyed() {
    console.log('8. destroyed');
  },
  methods: {
    // 毀掉vm
    destroyVm() {
      this.$destroy();
    },
  },
});

每日一句法文有益身心:Ça va ? --> 撒.v 娃? --> 還好嗎? --> 你還好嗎?oui, ça va !


上一篇
Vue 實作一個簡單的 Todo List [下]
下一篇
Vue 過渡與動畫效果 Transitioning Single Elements/Component
系列文
Déjà-vu ? 要 Vue 過才知道30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言