iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 3
1
Modern Web

用範例理解 Vue.js系列 第 3

用範例理解 Vue.js #3:Vue Instance & Instance Lifecycle Hooks

https://ithelp.ithome.com.tw/upload/images/20171213/20107107MSMEVwiTps.png

Vue Instance

每個 Vue 的應用都是通過 new Vue() 來建立 Vue Instance

建立 Vue Instance

下面建立了一個名為 vm 的 Vue Instance,「vm」為 view model 的簡稱。

var vm = new Vue({
  // options
})

view model 來自設計模式 MVVM - model、view 和 view model。

傳入選項物件

在實體化時,可傳入一個選項物件,結構會像是這樣:

{
  el: '#id',    // CSS selector 或 HTMLElement 實例
  props: {},    // Array<string> 或 Object
  data: {},     // Object 或 Function
  computed: {}, // { [key: string]: Function | { get: Function, set: Function } }
  methods: {},  // { [key: string]: Function }
  watch: {},    // { [key: string]: string | Function | Object }
  mounted() {}  // Function
  // ...
}

Instance Lifecycle Hooks

每個 Vue Instance 在建立時都會經歷一系列初始化步驟,例如,需要設置數據觀察,編譯模板,將實例掛載到 DOM,以及在數據更改時更新 DOM。在初始化過程中,它還運行稱為生命週期鉤子 (Instance Lifecycle Hooks) 的函數,讓開發者可在特定階段添加自己的代碼。

例如:created 鉤子可以用來在創建實例之後運行代碼:

附上 fiddle (https://jsfiddle.net/hunterliu/8fw120n2/)

new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` points to the vm instance
    console.log('a is: ' + this.a)
  }
})
// => "a is: 1"

另外還有其他鉤子將在實例生命週期的不同階段被調用,比如:

  • mounted
  • updated
  • destroyed

注意:鉤子中的 this 指向調用它的 Vue Instance。

Lifecycle Diagram

下圖說明了 Vue Instance 的生命週期。
伴隨著對 Vue 的了解,整體的概念也會更清晰。

在看範例之前先附上官方 Lifecycle Diagram,方便對照。

https://ithelp.ithome.com.tw/upload/images/20171213/20107107zUBO3prUec.png

可以從 Lifecycle Diagram 看到這些鉤子有:

beforeCreate

在 Vue Instance 初始化之後,但在 data observer 和 event/watcher 被設置之前被執行。

不精確白話文為:此刻你無法調用 data 及 methods。

created

Vue Instance 已初始化完成,已設置 data, computed, methods, watch/event callbacks,但尚未開始mounting階段,且 $el 目前也未掛載。

不精確白話文為:此刻已經可以調用 data, computed, methods, watch等數據或函式。

beforeMount

mounting階段開始前被調用:render function首次被調用。

mounted

選項物件中的el被新創建的vm.$el替換,並掛載到到 vm 上,並調用mounted這個鉤子。

beforeUpdate

數據被更新時會調用,發生在 Virtual DOM re-render 和 patch 之前(連結:Day4: Virtual DOM),可以在此時更改狀態數據,並不會增加重新渲染的成本。

updated

由於數據更新導致 Virtual DOM re-render 和 patch 之後會調用updated這個鉤子。

不精確白話文為:由於updated被調用時,DOM 已經更新。所以在此時更新數據很可能會導致updated無限循環的被調用。

beforeDestroy

在 Vue Instance 被銷毀前被調用,因此 Vue Instance 在beforeDestroy中仍可運作。

不精確白話文為:Vue Instance 可以在此時做垂死前的掙扎。

destroyed

在 Vue Instance 被銷毀後被調用,此時 Vue Instance 所有東西會解除綁定,事件監聽也都會被移除,子實例也會被銷毀。

用範例逐步看 Create, Mount, Update, Destroy

用一個範例逐步看到所有的鉤子被調用,並在這個過程中理解被執行的原因。

首先定義一個 Vue Instance 為 vm,而 data 中 msg 的值為Hello Vus.js,並且當每個鉤子被執行時,簡單的用console.log記錄該鉤子被執行。

var vm = new Vue({
  data: {
    msg: 'Hello Vus.js'
  },
  beforeCreate() {
    console.log('beforeCreate 被執行');
  },
  created() {
    console.log('created 被執行');
  },
  beforeMount() {
    console.log('beforeMount 被執行');
  },
  mounted() {
    console.log('mounted 被執行');
  },
  beforeUpdate() {
    console.log('beforeUpdate 被執行');
  },
  updated() {
    console.log('updated 被執行');
  },
  beforeDestroy() {
    console.log('beforeDestroy 被執行');
  },
  destroyed() {
    console.log('destroyed 被執行');
  }
});

注意:此時 Vue Instance 中的選項物件暫時還沒有指定el: '#app',也請觀察以下四個步驟 HTML 的變化。

看範例時請打開 console。

beforeCreate & created

若此時我們直接運行以上代碼,會發現只有beforeCreatecreated被執行,因為在整個 Vue Instance 的生命週期執行到created之後,會先判斷是否有el這個選項,因為這邊並沒有定義el,因此需要等到 vm.$mount(el)被呼叫時,整個生命周期才會繼續進行。

此時的 HTML 顯示 {{msg}}

附上 fiddle beforeCreate & created

beforeMount & mounted

若添加以下代碼:

vm.$mount('#app');

beforeMountmounted會被執行,而在範例中額外添加了setTimeout為的是明顯區隔CreateMount分開被執行。

此時的 HTML 顯示 Hello Vus.js

附上 fiddle beforeMount & mounted

beforeUpdate & updated

當 vm 中的 data 有異動時,例如修改 msg的值:

vm.$data.msg = 'change msg';

beforeUpdateupdated會被執行。

此時的 HTML 顯示 change msg

附上 fiddle beforeUpdate & updated

beforeDestroy & destroyed

可以透過 vm.$destroy()銷毀 Vue Instance。

vm.$destroy();

beforeDestroydestroyed會被執行。

此時的 HTML 顯示 change msg

附上 fiddle beforeUpdate & updated

完整測試範例

完整測試範例不只是把所有的鉤子執行一遍,也觀察了數據和DOM的變化。

看範例時請打開 console。

Lifecycle Hook 完整測試範例

參考資料


上一篇
用範例理解 Vue.js #2:用七個官方範例初步認識 Vue.js
下一篇
用範例理解 Vue.js #4:Virtual DOM
系列文
用範例理解 Vue.js30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

我要留言

立即登入留言