mpvue小程序开发 - 生命周期梳理

转自IMWeb社区,做者:llunnn,原文连接前端

最近在开发小程序,尝试性地使用了一下mpvue框架。vue

mpvue 是一个使用 Vue.js 开发小程序的前端框架。框架基于 Vue.js 核心,mpvue 修改了 Vue.js 的 runtime 和 compiler 实现,使其能够运行在小程序环境中,从而为小程序开发引入了整套 Vue.js 开发体验。web

mpvue同时维护了Vue和小程序的两套机制,所以须要对两套机制进行关联。这里主要对mpvue的生命周期来进行一些梳理。小程序

微信小程序生命周期

首先咱们须要了解,微信小程序的生命周期:微信小程序

App对象,主要有onLaunch, onShow和onHide。浏览器

Page对象,主要有onLoad, onShow, onReady, onHide和onUnload。前端框架

Vue到mpvue

mpvue的出现使得咱们能够用书写Vue实例的方式去声明这两种对象,并使得Vue实例兼容小程序的生命周期。微信

Vue的生命周期主要体如今8个钩子:beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeDestroy, destroyed。app

来对比一下Vue和mpvue的生命周期,看一下mpvue作出了什么改变:框架

对比来看,mpvue主要是对created和beforeMount之间的过程作了改变。

在Vue中,这个阶段主要做用是将template编译为render函数:

而在mpvue中,对于App或Page组件(这里的Is App or Page component应该要解释为“是否为App或Page组件”),为他们初始化小程序的生命周期,并注册App对象或Page对象:

这里能够看出来,mpvue中,Vue和小程序生命周期钩子触发的基本顺序是beforeCreate -> created -> onLaunch/onLoad -> onShow -> onReady -> beforeMount -> mounted -> ...

实践验证

这里有一个入口页面,包含一个经过wx.navigateTo跳转到newPage的按钮。

newPage中包含一个card组件,和一个经过wx.navigateBack跳转回入口页面的按钮。

在App, newPage和card的各个生命周期钩子输出信息,来观察它们的触发状况和顺序。

在App被建立,跳转到newPage前

咱们能够观察到,app对象首先被建立,触发onLaunch和onShow。

在这以后,newPage被create。须要注意的是,此时咱们尚未跳转到newPage,也就是说在mpvue中,不管页面是否被访问到,其Vue实例的beforeCreate和created都在app建立后就被触发。

第一次跳转到newPage并返回入口页面

因为newPage页面的beforeCreate和created已经提早被触发过了,在调用了wx.NavigateTo跳转到newPage时,先触发小程序的生命周期,再触发beforeMount,这时候开始建立子组件card的实例,按照beforeCreate -> created -> onLoad -> onReady -> beforeMount -> mounted 的顺序触发生命周期钩子。(这里组件的onShow为何没有触发..须要再深刻探究一下)

在wx.navigateBack时,小程序的生命周期钩子onUnload被触发。但须要注意的是:Vue的生命周期钩子beforeDestroy和destroyed并无被触发,也就是说小程序中newPage的page对象被卸载了,但newPage和card的Vue实例并无被销毁。

第二次跳转到newPage并返回入口页面

newPage和card都已经被create且没有destroy,在再次wx.navigateTo时将直接从onLoad -> onShow -> onReady开始触发,newPage的mount和update过程也会出发,而component以后update过程被触发了。这里能够发现,在onLoad以后还通过了几个阶段,才开始触发Vue实例的生命周期钩子,而上一次保存在内存中的数据并无被destroy,所以在从新加载的过程当中,Vue实例还保存着上一次加载页面时的数据。

开发时遇到的问题

遇到的问题主要是由create过程在页面加载前就被统一触发引发的。 在使用Vue时,常常在created钩子中得到新的data。由于此时对data的数据观测已经被创建,可是页面内容还没有被挂载,Vue实例能够观测到data的变化并在视图显示出来以前改变其内容。

若是在mpvue中,咱们想获取页面路由query中的数据,或是想在页面建立时请求接口,咱们可能会这样考虑:

在created中获取数据? 在mpvue中,created只被触发一次,且在页面建立前被触发,也就是说query中的数据是没法得到的,再次访问页面时若是数据发生了变化,created中的逻辑也并不会再次执行。

推迟到beforeMount? 从功能上说,在beforeMount获取数据是没有问题的。但因为页面unload时没有触发destroy,在再次加载页面时,Vue实例仍然保存着前一次得到的数据,而页面的onLoad、onShow均在beforeMount以前被触发,实践时会发现,页面在数据更新以前就会被显示出来,旧的数据会在页面中“一闪而过”。

在onLoad中获取数据? 实践证实这的确是一种最稳妥的方法,数据能被正确地设置,页面也不会“闪”。 可是官方文档有这样一句话: 除特殊状况外,不建议使用小程序的生命周期钩子。 这里大概是为了代码的移植性作考虑吧,不知道这里算不算特殊状况呢。

使用computed? 为了不使用小程序的生命周期钩子,还能够考虑使用computed的来获取query中的内容,而query须要在页面onLoad以后才存在,这里须要注意作一些判断。

总结

从Vue过分到mpvue仍是很是平滑的,特别是在有太小程序开发经验的状况下。可是因为小程序自己和浏览器的差别,使得开发过程当中会遇到一些难以理解的问题,将生命周期作一下梳理对更顺利地进行开发是有一些好处的。

可是,从这里也能够看到,对于开发小程序来讲,mpvue实际上额外地维护了一套Vue的机制,并对小程序的事件、数据进行代理、同步,实际上这个过程可能会形成一些性能上的损耗。再加上mpvue目前仍是存在一些缺陷,而小程序也支持了数据绑定、组件化开发,我的认为如果追求高质量的开发仍是直接使用原生小程序更优吧~