mpvue是美团基于vue开发的一个开发小程序的框架,从而以vue的语法来开发小程序。在生命周期上,mpvue同时支持了vue的生命周期和小程序的生命周期,这可能让新上手的同窗费解。这篇文章就来说讲mpvue的混合生命周期。vue
在深刻以前,先说一个mpvue开发中的常见的坑。假设你在一个页面中有打开了一个弹窗,而后在没有关闭的状况下返回上一页,而后再从新进入时,弹窗依然在那里。按道理说,返回上一页时,弹窗所在的page实例已经被unload了,为何再次进入弹窗还在呢,这实际上是mpvue混合生命周期搞的鬼。git
在理解mpvue的生命周期前,咱们先看一下官方给出的一张图:
github
不得不说这张图作的真心有点糙,mpvue原本就不须要传el这个option,结果仍是出如今生命周期图示中。。。将el换成page实例却是更贴切一些。相信很多同窗对mpvue的生命周期仍是有点晕的。下面咱们从新梳理一下各个钩子在何时触发。小程序
这里以官方的mpvue/mpvue-quickstart
项目来演示小程序的生命周期函数到底在何时触发,项目代码能够参考官方教程得到。app
研究触发过程的作法简单粗暴,就是直接在各个生命周期函数下打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
vue的created函数先于小程序onLoad函数调用ide
一个页面对应一个vue实例,app也对应一个vue实例(打印出的this)函数
在小程序的第一页出现前,已经建立出了全部页面对应的Vue实例。看下图能够看出,在index页面的onLoad触发前,page counter,logs的created函数已经触发。ui
mounted会在onReady以后触发,这个钩子适用于当页面出现时执行一些过渡效果的状况。
有同窗可能会觉得vue的实例是和小程序的page实例一块儿出现的,然而事实并非这样。
vue的实例在页面显示以前就已经被初始化了,也就是在main.js中执行new vue(App)
的时候。而小程序的页面则是按需加载的,当用户跳转到那个页面时,page实例才会建立。这个观点一样能够由vue实例下面的$mp
属性说明,这个属性关联了vue的实例和小程序页面的实例。
Tips: 当你须要使用wx.createSelectorQuery() 查询某个元素的位置时,应当放在onReady或者mounted的生命周期中进行,保证位置的准确性
这个属性在原生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生命周期函数下打印的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