Vue 實例中的生命周期鉤子

Vue 實例中的生命周期鉤子

本博客版權歸本人和饑人谷所有,轉載需說明來源
Vue 框架的入口就是 Vue 實例,其實就是框架中的 view model ,它包含頁面中的業(yè)務
處理邏輯、數(shù)據(jù)模型等,它的生命周期中有多個事件鉤子,讓我們在控制整個Vue實例的
過程時更容易形成好的邏輯。

Vue 實例

在文檔中經(jīng)常會使用 vm 這個變量名表示 Vue 實例,在實例化 Vue 時,需要傳入一個選
項對象,它可以包含數(shù)據(jù)(data)、模板(template)、掛載元素(el)、方法(methods)、生
命周期鉤子(lifecyclehook)等選項。

Vue 實例化的選項

需要注意的是含 this 的函數(shù)大多不要使用箭頭函數(shù),因為我們期望 this 指向 Vue 實例。

data

Vue 實例的數(shù)據(jù)都保存在 data 對象中,Vue 將會遞歸將 data 的屬性轉換為 getter/setter,
從而讓 data 的屬性能夠響應數(shù)據(jù)變化。

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

這樣數(shù)據(jù)就綁定在 HTML 中,Vue 框架監(jiān)視 data 的數(shù)據(jù)變化,自動更新 HTML 內(nèi)容。

computed

計算屬性將被混入到 Vue 實例中。所有 getter 和 setter 的 this 上下文自動地綁定為 Vue
實例。官方API

var vm = new Vue({
  data: { a: 1 },
  computed: {
    // 僅讀取,值只須為函數(shù)
    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,那么值就可以是普通函數(shù),但是必須有返回值。

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 看起來可以做同樣的事情,單純看結果兩種方式確實是相同的。
然而,不同的是計算屬性是基于它們的依賴進行緩存的。計算屬性只有在它的相關依賴發(fā)生改變
時才會重新求值。這就意味著只要 message 還沒有發(fā)生改變,多次訪問 reversedMessage 計算屬性會
立即返回之前的計算結果,而不必再次執(zhí)行函數(shù)。相比而言,只要發(fā)生重新渲染,method 調(diào)用總會執(zhí)行
該函數(shù)。

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

一個對象,鍵是需要觀察的表達式,值是對應回調(diào)函數(shù)。值也可以是方法名,或者包含選項的對象。Vue
實例將會在實例化時調(diào)用 $watch(),遍歷 watch 對象的每一個屬性。

var vm = new Vue({
  data: {
    a: 1,
    b: 2,
    c: 3
  },
  watch: {
    // 監(jiān)控a變量變化的時候,自動執(zhí)行此函數(shù)
    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 實例有一個完整的生命周期,也就是從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載Dom→渲染、更新→渲染、卸載等一系列
過程,我們稱這是 Vue 的生命周期。通俗說就是 Vue 實例從創(chuàng)建到銷毀的過程,就是生命周期。

在Vue的整個生命周期中,它提供了一些生命周期鉤子,給了我們執(zhí)行自定義邏輯的機會。

接下來我們用幾個例子來看看生命周期鉤子是怎么用的:

完整的代碼托管在 codepen

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

我們對 input 和 p 綁定了data 對象的 number 數(shù)據(jù),Vue 實例構建如下:

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

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

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

我們再試著去更改 input 輸入框中的內(nèi)容,可以看到輸入框上方的數(shù)據(jù)同步發(fā)生改變,這就是數(shù)據(jù)綁定的效果,在更
新數(shù)據(jù)時觸發(fā) beforeUpdate 和 updated 鉤子,且在 beforeUpdate 觸發(fā)時,數(shù)據(jù)已更新完畢。

而 destroy 僅在調(diào)用app.$destroy();時觸發(fā),對 vue 實例進行銷毀。銷毀完成后,我們再重新改變 number 的值,vue 不再對此動作
進行響應了。但是原先生成的dom元素還存在,可以這么理解,執(zhí)行了destroy操作,后續(xù)就不再受vue控制了。

Vue.nextTick

在下次 DOM 更新循環(huán)結束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個方法,獲取更新后的 DOM。官方API

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

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

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

什么時候需要到Vue.nextTick()

  1. 在 Vue 生命周期的 created() 鉤子函數(shù)進行的 DOM 操作一定要放在 Vue.nextTick() 的回調(diào)函數(shù)中。原因是什么呢,原因是
    在 created() 鉤子函數(shù)執(zhí)行的時候 DOM 其實并未進行任何渲染,而此時進行 DOM 操作無異于徒勞,所以此處一定要將 DOM 操作
    的 js 代碼放進 Vue.nextTick() 的回調(diào)函數(shù)中。與之對應的就是 mounted 鉤子函數(shù),因為該鉤子函數(shù)執(zhí)行時所有的 DOM 掛載和
    渲染都已完成,此時在該鉤子函數(shù)中進行任何DOM操作都不會有問題 。
  2. 在數(shù)據(jù)變化后要執(zhí)行的某個操作,而這個操作需要使用隨數(shù)據(jù)改變而改變的 DOM 結構的時候,這個操作都應該放
    進 Vue.nextTick() 的回調(diào)函數(shù)中。

生命周期小結

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

beforecreate : 可以在這加個loading事件,在加載實例時觸發(fā)
created : 初始化完成時的事件寫在這里,如在這結束loading事件,異步請求也適宜在這里調(diào)用
mounted : 掛載元素,獲取到DOM節(jié)點
updated : 如果對數(shù)據(jù)統(tǒng)一處理,在這里寫上相應函數(shù)
beforeDestroy : 可以做一個確認停止事件的確認框
nextTick : 更新數(shù)據(jù)后立即操作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 指令設置了延時,在每次輸
入后延時同步輸入框的數(shù)據(jù),減少了更新次數(shù),提高性能。

GitHub 提交

這個例子從 Github 的 API 中獲取了最新的 Vue.js 提交數(shù)據(jù),并且以列表形式將它們展示了出
來。你可以輕松地切換 master 和 dev 分支。

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

在 created 鉤子中用聲明的 fetchData 函數(shù)獲取ajax異步數(shù)據(jù)并渲染到頁面。

內(nèi)嵌組件

本例中,整合了第三方 jQuery 插件(select2),怎么做到的呢?就是把它內(nèi)嵌在一個常用組件中

mounted: function () {
    var vm = this
    $(this.$el)
      .val(this.value)
      // init select2
      .select2({ data: this.options })
      // emit event on change.
      .on('change', function () {
        vm.$emit('input', this.value)
      })
  },

這個例子建立了組件 select2 ,在 mounted 鉤子中增加了 jQuery 插件 select2 的方法,數(shù)據(jù)加載時給元素增加這幾個方法,獲取 DOM 數(shù)據(jù)。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Vue 框架的入口就是 Vue 實例,其實就是框架中的 view model ,它包含頁面中的業(yè)務 處理邏輯、數(shù)據(jù)...
    云中一樵夫閱讀 1,161評論 0 1
  • Vue 框架的入口就是 Vue 實例,其實就是框架中的 view model ,它包含頁面中的業(yè)務處理邏輯、數(shù)據(jù)模...
    阿根廷斗牛閱讀 961評論 0 2
  • Vue 實例 在文檔中經(jīng)常會使用 vm 這個變量名表示 Vue 實例,在實例化 Vue 時,需要傳入一個選項對象,...
    鄙人才疏學淺閱讀 654評論 0 1
  • 前段時間突然思考起一個問題:人生的意義是什么?看完卡耐基《人性的弱點》后,我仿佛找到了答案。雖然書中重點談及...
    Caroline喬喬閱讀 551評論 0 4
  • 悶熱的天氣依然持續(xù)著,今天星期天,我決定放飛孩子,讓他玩一下,不用寫作業(yè)了,很高興的和小朋友玩去了,九點左右爺爺...
    博碩媽閱讀 248評論 0 0

友情鏈接更多精彩內(nèi)容