llunnn

2018-09-05 10:40

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

Vue

本文作者:IMWeb llunnn 原文出处:IMWeb社区 未经同意,禁止转载

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

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

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。

来对比一下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目前还是存在一些缺陷,而小程序也支持了数据绑定、组件化开发,个人认为若是追求高质量的开发还是直接使用原生小程序更优吧~

0条评论

    您需要 注册 一个IMWeb账号或者 才能进行评论。