理解mpvue的生命週期

mpvue是美團基於vue開發的一個開發小程序的框架,從而以vue的語法來開發小程序。在生命週期上,mpvue同時支持了vue的生命週期和小程序的生命週期,這可能讓新上手的同窗費解。這篇文章就來說講mpvue的混合生命週期。vue

一個bug

在深刻以前,先說一個mpvue開發中的常見的坑。假設你在一個頁面中有打開了一個彈窗,而後在沒有關閉的狀況下返回上一頁,而後再從新進入時,彈窗依然在那裏。按道理說,返回上一頁時,彈窗所在的page實例已經被unload了,爲何再次進入彈窗還在呢,這實際上是mpvue混合生命週期搞的鬼。git

mpvue的生命週期

在理解mpvue的生命週期前,咱們先看一下官方給出的一張圖: <img width="300px" src="http://mpvue.com/assets/lifecycle.jpg">github

不得不說這張圖作的真心有點糙,mpvue原本就不須要傳el這個option,結果仍是出如今生命週期圖示中。。。將el換成page實例卻是更貼切一些。相信很多同窗對mpvue的生命週期仍是有點暈的。下面咱們從新梳理一下各個鉤子在何時觸發。小程序

這裏以官方的mpvue/mpvue-quickstart項目來演示小程序的生命週期函數到底在何時觸發,項目代碼能夠參考官方教程得到。app

console.log

研究觸發過程的作法簡單粗暴,就是直接在各個生命週期函數下打console.log。mpvue-quickstart有3個頁面,分別是index,counter和logs,下面咱們給這3個頁面加上以下生命週期函數:框架

created() {
    console.log('page index created', this)
  },
  mounted() {
    console.log('mounted', this)
  },
  onLoad() {
    console.log('page index onLoad', this)
  },
  onReady () {
    console.log('page index onReady', this)
  },
  onShow() {
    console.log('onShow', this)
  },
  onUnload() {
    console.log('onUnload', this)
  },
  onHide() {
    console.log('onHide', this)
  },

完成後,從新編譯小程序,控制檯打印的日誌以下圖,分析能夠看出如下結論:dom

  1. vue的created函數先於小程序onLoad函數調用ide

  2. 一個頁面對應一個vue實例,app也對應一個vue實例(打印出的this)函數

  3. 在小程序的第一頁出現前,已經建立出了全部頁面對應的Vue實例。看下圖能夠看出,在index頁面的onLoad觸發前,page counter,logs的created函數已經觸發。ui

  4. mounted會在onReady以後觸發,這個鉤子適用於當頁面出現時執行一些過渡效果的狀況。

有同窗可能會覺得vue的實例是和小程序的page實例一塊兒出現的,然而事實並非這樣。

vue的實例在頁面顯示以前就已經被初始化了,也就是在main.js中執行new vue(App)的時候。而小程序的頁面則是按需加載的,當用戶跳轉到那個頁面時,page實例纔會建立。這個觀點一樣能夠由vue實例下面的$mp屬性說明,這個屬性關聯了vue的實例和小程序頁面的實例。

Tips: 當你須要使用wx.createSelectorQuery() 查詢某個元素的位置時,應當放在onReady或者mounted的生命週期中進行,保證位置的準確性

$mp屬性

這個屬性在原生vue中是沒有的,它是由mpvue擴展出的屬性,能夠類比原生vue中的$el。在網頁中,$el指向vue驅動的dom元素。而在小程序中,$mp指向vue驅動的page或者app實例。

下面咱們看看index和counter兩個頁面對應的vue實例下$mp屬性的區別:

當頁面load後,$mp爲ready狀態,而且有page屬性指向這個頁面實例,而頁面尚未load時,$mp屬性爲register狀態,沒有page屬性。也就是說,空有vue實例,可是並無page能夠給他操做。

onUnLoad方法調用後,相應頁面vue實例還在嗎?

上面是在onUnload生命週期函數下打印的this,可見this也就是vue實例並無被銷燬,而小程序的page實例被銷燬了。因此vue內部的狀態會被保存,如彈窗打開關閉的狀態。假設這個狀態由this.showModal控制

data(){
return {
    showModal: false// 彈窗爲關閉狀態
}
}

當頁面再次被打開時,若是上次頁面this.showModal爲true,則頁面剛出現時彈窗就仍是打開的。這就解釋了文章一開頭的那個問題。因此,若是你但願當頁面被關閉時,狀態不被保存的話,須要在onUnload方法下處理相關邏輯,或者在onShow時重置data裏的狀態

// ...
onUnload(){
    this.showModal = false
}
// 更通用一點
onUnload() {
    Object.assign(this, this.$options.data())
}

總結:儘管mpvue同時支持了小程序的生命週期和vue的生命週期,可是二者之間並非共生共滅的關係。更多閱讀能夠參考這個官方倉庫的issue-同一路由切換時,上一次的頁面數據會保留 #140

相關文章
相關標籤/搜索