《微信小程序七日谈》系列文章:

  1. 第一天:人生若只如初见
  2. 第二天:你可能要抛弃原来的响应式开发思维
  3. 第三天:玩转Page组件的生命周期
  4. 第四天:页面路径最多五层?导航可以这么玩

前两篇文章第一天:人生若只如初见第二天:你可能要抛弃原来的响应式开发思维零零散散地记录了一些微信小程序的细节,主要集中在UI方面。其中提到的解决方案只是笔者自身的一些探索,并非最佳实践,甚至不是笔者项目中最后采用的方案(最终方案会在后续文章里详细讲述)。其实小程序的UI开发并非简短的两篇文章可以概括的,还有许多细节待挖掘,奈何项目排期紧张,暂时就不去研究与当前需求无关的东西了。

今天这篇文章简单记录一下在使用小程序Page组件时对于其生命周期的一些使用心得。

钩子函数的命名技巧

官方文档对Page的生命周期的介绍简单明了,在生命周期的不同阶段抛出的钩子函数依次为: onLoad -> onShow -> onReady -> onHide -> onUnload

使用过React的开发者肯定会对用on做为钩子函数命名前缀非常不舒服,React使用will、did、should等一系列有时态语义的词汇命名钩子函数,令开发者一眼就能分辨钩子函数对应的生命周期阶段。但是on是具有一定歧义的。浏览器的用户行为事件机制,以及我们所熟悉的jQuery中,使用on作为捕获/监听事件的API命名,这种情形下可以把on理解为当某件事情发生时做某些行为,这也是大部分前端工程师对on语义的理解。这种理解的on有一层拦截的意思,比如onclick先于<a>href跳转,可以拦截其默认的click行为,在默认click之前发生。但是请大家仔细思考一下window.onloadon的含义。onload的触发时机是在文档加载完成之后,在执行我们定义的onload逻辑之前,文档已经完成了load行为。也就是说,onload并没有拦截load行为,而是在load事件之后发生。所以,on这个词汇并不能精准的形容到底是前还是后,它是没有时态语义的。

具体到Page的生命周期钩子函数,大家请凭第一感觉理解下面几个函数的执行时机:

  • onLoad
  • onShow
  • onReady

我相信大部分人对于这三者的理解是:钩子函数在load/show/ready完成之后执行。跟window.onload是一样的。那么请大家在思考下列两个的执行时机:

  • onHide
  • onUnload

跟前三者是一样的吗?

我们先不去探究后两者与前三者的执行时机策略是否相同。请大家先以常规的思维思考下列的应用场景:app导航栏左上角有个“返回”按钮,如下图:

很常见的一个逻辑是:如果用户在未保存表单数据之前点击返回按钮的话,通常会弹出一个提示层,如下:

也就是说,页面有个beforeUserLeave的策略,在执行userLeave之前进行拦截并给出提示,以免用户的操作失误。这不仅仅是业务逻辑的需求,也是一个网站从开始到被关闭过程中的一环,这就是我们熟知的window.onbeforeunload事件。

同样,笔者参与的项目也有上述的业务逻辑,在用户离开页面之前提示用户的编辑状态。对应小程序的几个钩子函数,结合React和Vue的开发经验,自然而然地就想到在onHide或者onUnload内拦截返回操作并给出提示。

但是,并不行!onHideonUnload的执行时机策略竟然跟onLoad/onShow/onReady一样!

也就是说,在page被卸载之后才会执行onUnload。这就造成用户点击返回按钮,已经回到了上一个页面,然后,突然弹出了一个提示框:

用户:WTF?

钩子函数的正确执行时机

其实官方文档详细展示了Page的各个钩子函数的执行时机,如下图:

从上图中可以看出:

  • onHide是在当前Page被“set to background”之后触发;
  • onUnload是在当前Page被“destory”之后触发。

当然,每个人设计组件时对组件的生命周期都有自己的理解和实现,并不是说小程序的Page生命周期设计的不好,只是希望能够提供更细化的钩子函数,比如上文提到的“before”策略,以便实现更人性化的用户体验。

data全部动态化

vue.js的1.x版本提供了activate钩子函数,这个钩子阻塞了组件的后续执行,方便开发者在组件渲染之前进行特殊处理,比如使用jsonp请求数据,成功后执行done()触发组件的后续流程。

小程序里有没有阻塞的钩子函数呢?

可能大部分人跟笔者一样,第一个想法就是试试onShow是否是阻塞的,但是结果并不像预期的那样。小程序的Page组件没有提供阻塞的钩子函数,根据上文中的官方配图可以看到,在组件的data更新之后有个"Rerender"动作。Page组件的数据统一为data,而不是像React或者Vue区分propsstate/data。这种设计的优点是不用特意的对某个data进行监听,data全部是动态的,这意味着任何一个data的改变都会触发Rerender。

小程序提供一些内置的UI组件,但是逻辑组件只有apppage两种,并且两者并不是严格的父子组件关系。所以,page组件并不需要类似React中的props数据,所有的数据都属于自身。

总结

Page组件的生命周期十分简洁,上手容易。但是面对一些特殊需求时并不能提供很好的支持。这种情况下我们不得不适当地修改需求逻辑。
小程序中并没有父子组件的关系谱,组件的数据不会区分propsstate,全部是统一的data,并且全部是动态的。任何data的修改都会触发Rerender。

最近发现有些网站、个人博客以及微信公众号未经授权转载了笔者的文章,作为技术人员,希望大家都具有基本的职业道德。剽窃的技术是不会得到尊重的,对于未经授权的转载方,必要的时候会付诸法律手段。

《微信小程序七日谈》- 第三天:玩转Page组件的生命周期的更多相关文章

  1. 《微信小程序七日谈》- 第四天:页面路径最多五层?导航可以这么玩

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...

  2. 《微信小程序七日谈》- 第二天:你可能要抛弃原来的响应式开发思维

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 上篇文 ...

  3. 《微信小程序七日谈》- 第一天:人生若只如初见

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...

  4. 《微信小程序七日谈》- 第五天:你可能要在登录功能上花费大力气

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...

  5. 《微信小程序七日谈》- 第六天:小程序devtool隐藏的秘密

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...

  6. 《微信小程序七日谈》- 第七天:不要捡了芝麻丢了西瓜

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...

  7. 使用wepy开发微信小程序商城第三篇:购物车(布局篇)

    使用wepy开发微信小程序商城 第三篇:购物车(布局篇) 前两篇如下: 使用wepy开发微信小程序商城第一篇:项目初始化 使用wepy开发微信小程序商城第二篇:路由配置和页面结构 基于上两篇内容,开始 ...

  8. 微信小程序把玩(三十三)Record API

    原文:微信小程序把玩(三十三)Record API 其实这个API也挺奇葩的,录音结束后success不走,complete不走,fail也不走, 不知道是不是因为电脑测试的原因,只能等公测或者等他们 ...

  9. 微信小程序把玩(三十四)Audio API

    原文:微信小程序把玩(三十四)Audio API 没啥可值得太注意的地方 重要属性: 1. wx.getBackgroundAudioPlayerState(object) 获取播放状态 2.wx.p ...

随机推荐

  1. 解决安卓SDK更新连不通问题

    http://wenku.baidu.com/link?url=d7t81OFF4_o2YF9iBne-azyovROGPGOozMgWKNyAIQK8vtI0mIjvzpfdOXg7KOobu202 ...

  2. 澳洲最大的华资快递公司ACE 签约动软微信商城系统!

    ACE-平安立达快递是澳洲最大的华资快递公司ACE平安立达,总部设在Boxhill,同时在中国成立了进口食品专营连锁加盟店“澳莱优品”,目前已经有近20家加盟店,14年底国内计划开到60家店. 201 ...

  3. 刷连记录的迟到检测---Table表格增加一列值

    公司OA新增加了 刷脸记录 ,用于查看自己是否迟到,但是没有什么提醒,于是乎自己写了一个脚本 刷连记录 类似于这样的: 运行脚本后,是这个样子的: 擦,我本月已经迟到了 3次了.... 拖拽 刷脸记录 ...

  4. go语言实现一个简单的登录注册web小程序

    最近学习golang也有一段时间了,基础差不多学了个大概,因为本人是java程序员,所以对web更感兴趣.根据<go web编程>中的例子改编一个更简单的例子,供新手参考,废话不多说,上菜 ...

  5. Revit中如何控制图元的显示与隐藏

    Revit建模过程中经常会遇到图元的相互遮挡的情况,为了将一些图元显示出来,就需要将一些不需要显示的图元隐藏掉,这就需要用到"隐藏/重置"工具,在Revit绘图窗口左下角提供了一排 ...

  6. IntelliJ IDEA 2016.2.4 最新版激活方法

    新版激活方法: 1.在线激活 2016年7月14日 更新: 该域名已无法激活,参见2016.2 的搭建授权服务器激活, 菜单help >>>> Register 选择Licen ...

  7. 基于apt实现的Android快速持久化框架:AptPreferences

    AptPreferences是基于面向对象设计的快速持久化框架,目的是为了简化SharePreferences的使用,减少代码的编写.可以非常快速地保存基本类型和对象.AptPreferences是基 ...

  8. Maven3路程(二)Eclipse集成Maven

    我的环境: Eclipse:eclipse-jee-juno-SR2-win32 Maven:Maven3.0.5 1.Help->Eclipse Marketplace 2.选中要安装的插件, ...

  9. C# RSA PEM解密字符

    1.第一步先用openssl将pem的key转换为der的key //bin>openssl.exe rsa -in rsakeydec.pem -outform der -out pri.de ...

  10. dnspod动态域名使用感受

    继花生壳不能用之后,3322也开始不太好用了,首先就是360把所有3322的域名全部判定为危险域名,甚至拦截程序对于3322url的api请求. 所以想把3322换成我们自己的独立域名,但是3322他 ...