《微信小程序七日谈》- 第三天:玩转Page组件的生命周期
《微信小程序七日谈》系列文章:
前两篇文章第一天:人生若只如初见和第二天:你可能要抛弃原来的响应式开发思维零零散散地记录了一些微信小程序的细节,主要集中在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.onload中on的含义。onload的触发时机是在文档加载完成之后,在执行我们定义的onload逻辑之前,文档已经完成了load行为。也就是说,onload并没有拦截load行为,而是在load事件之后发生。所以,on这个词汇并不能精准的形容到底是前还是后,它是没有时态语义的。
具体到Page的生命周期钩子函数,大家请凭第一感觉理解下面几个函数的执行时机:
onLoadonShowonReady
我相信大部分人对于这三者的理解是:钩子函数在load/show/ready完成之后执行。跟window.onload是一样的。那么请大家在思考下列两个的执行时机:
onHideonUnload
跟前三者是一样的吗?
我们先不去探究后两者与前三者的执行时机策略是否相同。请大家先以常规的思维思考下列的应用场景:app导航栏左上角有个“返回”按钮,如下图:

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

也就是说,页面有个beforeUserLeave的策略,在执行userLeave之前进行拦截并给出提示,以免用户的操作失误。这不仅仅是业务逻辑的需求,也是一个网站从开始到被关闭过程中的一环,这就是我们熟知的window.onbeforeunload事件。
同样,笔者参与的项目也有上述的业务逻辑,在用户离开页面之前提示用户的编辑状态。对应小程序的几个钩子函数,结合React和Vue的开发经验,自然而然地就想到在onHide或者onUnload内拦截返回操作并给出提示。
但是,并不行!onHide和onUnload的执行时机策略竟然跟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区分props和state/data。这种设计的优点是不用特意的对某个data进行监听,data全部是动态的,这意味着任何一个data的改变都会触发Rerender。
小程序提供一些内置的UI组件,但是逻辑组件只有app和page两种,并且两者并不是严格的父子组件关系。所以,page组件并不需要类似React中的props数据,所有的数据都属于自身。
总结
Page组件的生命周期十分简洁,上手容易。但是面对一些特殊需求时并不能提供很好的支持。这种情况下我们不得不适当地修改需求逻辑。
小程序中并没有父子组件的关系谱,组件的数据不会区分props和state,全部是统一的data,并且全部是动态的。任何data的修改都会触发Rerender。
最近发现有些网站、个人博客以及微信公众号未经授权转载了笔者的文章,作为技术人员,希望大家都具有基本的职业道德。剽窃的技术是不会得到尊重的,对于未经授权的转载方,必要的时候会付诸法律手段。
《微信小程序七日谈》- 第三天:玩转Page组件的生命周期的更多相关文章
- 《微信小程序七日谈》- 第四天:页面路径最多五层?导航可以这么玩
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...
- 《微信小程序七日谈》- 第二天:你可能要抛弃原来的响应式开发思维
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 上篇文 ...
- 《微信小程序七日谈》- 第一天:人生若只如初见
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...
- 《微信小程序七日谈》- 第五天:你可能要在登录功能上花费大力气
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...
- 《微信小程序七日谈》- 第六天:小程序devtool隐藏的秘密
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...
- 《微信小程序七日谈》- 第七天:不要捡了芝麻丢了西瓜
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...
- 使用wepy开发微信小程序商城第三篇:购物车(布局篇)
使用wepy开发微信小程序商城 第三篇:购物车(布局篇) 前两篇如下: 使用wepy开发微信小程序商城第一篇:项目初始化 使用wepy开发微信小程序商城第二篇:路由配置和页面结构 基于上两篇内容,开始 ...
- 微信小程序把玩(三十三)Record API
原文:微信小程序把玩(三十三)Record API 其实这个API也挺奇葩的,录音结束后success不走,complete不走,fail也不走, 不知道是不是因为电脑测试的原因,只能等公测或者等他们 ...
- 微信小程序把玩(三十四)Audio API
原文:微信小程序把玩(三十四)Audio API 没啥可值得太注意的地方 重要属性: 1. wx.getBackgroundAudioPlayerState(object) 获取播放状态 2.wx.p ...
随机推荐
- DataWindow.Net 2.5 配置
在用过的所有的开发工具中,感觉最简单好用的就数PB了,他的DataWindow最方便,拖拖拽拽就把报表做好了,可惜现在很少人有用了.现在C/S系统一般用C#来做,但是做报表的时候总感觉没有DataWi ...
- iOS中dyld缓存的实现原理是怎样的?
在iOS开发中,为了提升系统的安全性,很多系统库文件都被打包到一个缓存的文件当中即dyld缓存,那大家对dyld缓存了解多少呢?今天小编将和大家分享的就是一位iOS大神对dyld缓存的使用分析,一起来 ...
- 那些在学习iOS开发前就应该知道的事(part 1)
英文原文:Things I wish I had known before starting iOS development—Part 1 http://www.cocoachina.com/ios/ ...
- Windows 系统下设置Nodejs NPM全局路径
Windows下的Nodejs npm路径是appdata,很不爽,想改回来,但是在cmd下执行以下命令也无效 npm config set cache "D:\nodejs\node_ca ...
- iOS 多渠道打包 编译脚本
http://webfrogs.me/2012/09/19/buildipa/http://blog.csdn.net/baxiaxx/article/details/8267295http://ic ...
- Android学习之Handler消息传递机制
Android只允许UI线程修改Activity里的UI组件.当Android程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户 ...
- Android 模拟器检测
参考链接:https://github.com/MindMac/HideAndroidEmulator 从多个方面识别模拟器1.用户习惯:联系人数量.短信数量.相册里面照片数量.安装的应用2.从IME ...
- Emit动态生成代码
Emit动态生成代码 引用:秒懂C#通过Emit动态生成代码 首先需要声明一个程序集名称, // specify a new assembly name var assemblyName = new ...
- Xcode工程使用CocoaPods管理第三方库新建工程时出现错误
工程使用CocoaPods管理第三方库,在新的目录update版本的时候出现如下问题 问题1描述: diff: /../Podfile.lock: No such file or director ...
- Linux流量监控工具-iftop教程
Linux流量监控工具-iftop教程http://automationqa.com/forum.php?mod=viewthread&tid=2854&fromuid=2