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

  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.onload中on的含义。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内拦截返回操作并给出提示。

但是,并不行!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组件的生命周期的更多相关文章

  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. Revit API 楼板开洞

    start [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] , , ) *  / , - ...

  2. Transistor 晶体管 场效应 双极型 达林顿 CMOS PMOS BJT FET

    Transistor Tutorial Summary Transistor Tutorial Summary Bipolar Junction Transistor Tutorial We can ...

  3. C# 设置和获取一个字节的某一位的值的方法

    自己工作中遇到需要对单字节的高位.低位进行赋值,即一个字节byte,想要给每一位都赋值,这个值是动态来的,是0或是1. 好不容易收集到一些珍贵资料,整理一下: 一.设置 方法code: /// < ...

  4. HTTP请求报文和HTTP响应报文(转)

    原文地址:http://blog.csdn.net/zhangliang_571/article/details/23508953 HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串, ...

  5. WPF 触发器

    属性触发器:数据触发器:事件触发器

  6. ip校验方法:判断ip是否位于指定的范围内

    import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.reg ...

  7. leveldb - menifest文件格式

    MANIFEST文件是Level DB的元信息文件,它里面的格式是leveldb的Log格式,一个menifest是一个record: void VersionEdit::EncodeTo(std:: ...

  8. 很好的一篇讲LTP在编解码中的作用的文章

    原文链接 LONG-TERM PREDICTION by: Adit Aviv       Kfir Grichman introduction: The speech signal has been ...

  9. SQL语句删除所有表

    ) )     ) )     ) )     ) ) )  TABLE_NAME  CONSTRAINT_NAME  CONSTRAINT_NAME  TABLE_NAME ) ) )  TABLE ...

  10. 基于Multisim的buck降压斩波电路仿真

    和boost电路相反,buck电路为DC-DC降压电路,搞了一下仿真发现低压情况下降压效率比較高,电压略微高一点降压效率就不敢恭维了. .不知道是怎么回事 仿真电路: 占空比D设置了0.5, U0=U ...