Vue 實例中的生命週期鉤子詳解

Vue 實例中的生命週期鉤子

Vue 框架的入口就是 Vue 實例,其實就是框架中的 view model ,它包含頁面中的業務
處理邏輯、數據模型等,它的生命週期中有多個事件鉤子,讓咱們在控制整個Vue實例的
過程時更容易造成好的邏輯。html

Vue 實例

在文檔中常常會使用 vm 這個變量名錶示 Vue 實例,在實例化 Vue 時,須要傳入一個選
項對象,它能夠包含數據(data)、模板(template)、掛載元素(el)、方法(methods)、生
命週期鉤子(lifecyclehook)等選項。vue

Vue 實例化的選項

須要注意的是含 this 的函數大多不要使用箭頭函數,由於咱們指望 this 指向 Vue 實例。ajax

data

Vue 實例的數據都保存在 data 對象中,Vue 將會遞歸將 data 的屬性轉換爲 getter/setter,
從而讓 data 的屬性可以響應數據變化。npm

var data = { a: 1 }
// 直接建立一個實例
var vm = new Vue({
  data: data
})
vm.a // -> 1
vm.$data === data // -> true

這樣數據就綁定在 HTML 中,Vue 框架監視 data 的數據變化,自動更新 HTML 內容。segmentfault

computed

計算屬性將被混入到 Vue 實例中。全部 getter 和 setter 的 this 上下文自動地綁定爲 Vueapi

實例。官方API緩存

var vm = new Vue({
  data: { a: 1 },
  computed: {
    // 僅讀取,值只須爲函數
    aDouble: function () {
      return this.a * 2
    },
    // 讀取和設置
    aPlus: {
      get: function () {
        return this.a + 1
      },
      set: function (v) {
        this.a = v - 1
      }
    }
  }
})
vm.aPlus   // -> 2
vm.aPlus = 3
vm.a       // -> 2
vm.aDouble // -> 4

這裏能夠省略setter,若是省略了setter,那麼值就能夠是普通函數,可是必須有返回值。app

methods

methods 將被混入到 Vue 實例中。能夠直接經過 VM 實例訪問這些方法,或者在指令表達
式中使用。方法中的 this 自動綁定爲 Vue 實例。官方API框架

var vm = new Vue({
  data: { a: 1 },
  methods: {
    plus: function () {
      this.a++
    }
  }
})
vm.plus()
vm.a // 2

看下面這個例子,methods 和 computed 看起來能夠作一樣的事情,單純看結果兩種方式確實是相同的。
然而,不一樣的是計算屬性是基於它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變
時纔會從新求值。這就意味着只要 message 尚未發生改變,屢次訪問 reversedMessage 計算屬性會
當即返回以前的計算結果,而沒必要再次執行函數。相比而言,只要發生從新渲染,method 調用總會執行
該函數。dom

var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // a computed getter
    reversedMessage: function () {
      // `this` points to the vm instance
      return this.message.split('').reverse().join('')
    }
  }
})

watch

一個對象,鍵是須要觀察的表達式,值是對應回調函數。值也能夠是方法名,或者包含選項的對象。Vue

實例將會在實例化時調用 $watch(),遍歷 watch 對象的每個屬性。

var vm = new Vue({
  data: {
    a: 1,
    b: 2,
    c: 3
  },
  watch: {
    // 監控a變量變化的時候,自動執行此函數
    a: function (val, oldVal) {
      console.log('new: %s, old: %s', val, oldVal)
    },
    // 深度 watcher
    c: {
      handler: function (val, oldVal) { /* ... */ },
      deep: true
    }
  }
})
vm.a = 2 // -> new: 2, old: 1

Vue 實例的生命週期

Vue 實例有一個完整的生命週期,也就是從開始建立、初始化數據、編譯模板、掛載Dom→渲染、更新→渲染、卸載等一系列
過程,咱們稱這是 Vue 的生命週期。通俗說就是 Vue 實例從建立到銷燬的過程,就是生命週期。

在Vue的整個生命週期中,它提供了一些生命週期鉤子,給了咱們執行自定義邏輯的機會。

接下來咱們用幾個例子來看看生命週期鉤子是怎麼用的:

完整的代碼託管在 codepen

HTML結構:

<div id="app">
  <p>{{ number }}</p>
  <input type="text" name="btnSetNumber" v-model="number">
</div>

咱們對 input 和 p 綁定了data 對象的 number 數據,Vue 實例構建以下:

var app = new Vue({         
    el: '#app',               
    data: {                   
      number: 1
    }
})

在實例中分別在每一個生命週期鉤子中 console.log('鉤子名稱',this.number) 咱們發現,第一次頁面加載時
觸發了 beforeCreate, created, beforeMount, mounted 這幾個鉤子,data 數據在 created 中可獲取到。

再去 console.log('mounted: ', document.getElementsByTagName('p')[0]) ,DOM 渲染在 mounted 中已經
完成。

咱們再試着去更改 input 輸入框中的內容,能夠看到輸入框上方的數據同步發生改變,這就是數據綁定的效果,在更
新數據時觸發 beforeUpdate 和 updated 鉤子,且在 beforeUpdate 觸發時,數據已更新完畢。

而 destroy 僅在調用app.$destroy();時觸發,對 vue 實例進行銷燬。銷燬完成後,咱們再從新改變 number 的值,vue 再也不對此動做
進行響應了。可是原先生成的dom元素還存在,能夠這麼理解,執行了destroy操做,後續就再也不受vue控制了。

Vue.nextTick

在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。官方API

Vue.nextTick(function () {
  // DOM 更新了
})

官方還提供了一種寫法,vm.$nextTick,用 this 自動綁定到調用它的實例上

created() {
    setTimeout(() => {
          this.number = 100
          this.$nextTick(() => {
            console.log('nextTick', document.getElementsByTagName('p')[0])
          })
    },100)
}

何時須要到Vue.nextTick()

  1. 在 Vue 生命週期的 created() 鉤子函數進行的 DOM 操做必定要放在 Vue.nextTick() 的回調函數中。緣由是什麼呢,緣由是
    在 created() 鉤子函數執行的時候 DOM 其實並未進行任何渲染,而此時進行 DOM 操做無異於徒勞,因此此處必定要將 DOM 操做

的 js 代碼放進 Vue.nextTick() 的回調函數中。與之對應的就是 mounted 鉤子函數,由於該鉤子函數執行時全部的 DOM 掛載和
渲染都已完成,此時在該鉤子函數中進行任何DOM操做都不會有問題 。

  1. 在數據變化後要執行的某個操做,而這個操做須要使用隨數據改變而改變的 DOM 結構的時候,這個操做都應該放

進 Vue.nextTick() 的回調函數中。

生命週期小結

生命週期鉤子的一些使用方法:

beforecreate : 能夠在這加個loading事件,在加載實例時觸發
created : 初始化完成時的事件寫在這裏,如在這結束loading事件,異步請求也適宜在這裏調用
mounted : 掛載元素,獲取到DOM節點
updated : 若是對數據統一處理,在這裏寫上相應函數
beforeDestroy : 能夠作一個確認中止事件的確認框
nextTick : 更新數據後當即操做dom

官方示例中的生命週期鉤子應用

一個極簡的Markdown編輯器

運行這個例子須要marked組件,經過如下方法引入:
在項目目錄下運行 npm i marked -S, js 文件中 import marked from 'marked' 便可。
這個例子沒有用到生命週期鉤子,簡單解讀一下這段代碼,

methods: {
    update: _.debounce(function (e) {
      this.input = e.target.value
    }, 300)
  }

html 中 textarea 綁定了 @input = "update" ,方法中用 debounce 指令設置了延時,在每次輸
入後延時同步輸入框的數據,減小了更新次數,提升性能。

GitHub 提交

這個例子從 Github 的 API 中獲取了最新的 Vue.js 提交數據,而且以列表形式將它們展現了出
來。你能夠輕鬆地切換 master 和 dev 分支。

created: function () {
    this.fetchData()
  },

在 created 鉤子中用聲明的 fetchData 函數獲取ajax異步數據並渲染到頁面。

相關文章
相關標籤/搜索