Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
imwebteam opened this issue Nov 8, 2018 · 1 comment
Open

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

imwebteam opened this issue Nov 8, 2018 · 1 comment

Comments

@imwebteam
Copy link
Contributor

本文作者: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做出了什么改变:

image4

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

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

image6

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

image8

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

实践验证

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

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

image10

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

在App被创建,跳转到newPage前

image12

我们可以观察到,app对象首先被创建,触发onLaunch和onShow。

在这之后,newPage被create。需要注意的是,此时我们还没有跳转到newPage,也就是说在mpvue中,无论页面是否被访问到,其Vue实例的beforeCreate和created都在app创建后就被触发。

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

image14

由于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并返回入口页面

image16

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

@tomastong
Copy link

之前一直用onLoad执行,只知道其它的不好使,文章写的很好豁然开朗~

页面的onLoad、onShow均在beforeMount之前被触发,实践时会发现,页面在数据更新之前就会被显示出来,旧的数据会在页面中“一闪而过”。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants