详解小程序如何改变onLoad的执行时机


Posted in Javascript onNovember 01, 2019

也许在小程序所有生命周期里,我们用的最多的就是 onLoad,一大堆代码都要在初始化的时候执行。

很多时候,初始化的代码是每个页面共用的,比如获取用户信息、获取定位等:

Page({
 onLoad() {
  this.userData = getUserData()
  wx.getLocation({
   type: 'wgs84',
   success (res) {
    // 业务代码
    // ...
   }
  })
 }
 // ...
})

久而久之,每个页面的 js 里都是如上的重复代码。如果可以先执行完通用的初始化代码,再执行每个页面各自的 onLoad 多好,可惜小程序并没有提供类似的钩子函数,那就自己来吧。

代理 onLoad

按照前几篇的方法,可以代理原有的 onLoad 事件:

var originPage = Page

function MyPage(config) {
 this.lifetimeBackup = {
  onLoad: config.onLoad
 }
 config.onLoad = function(options) {
  // 自定义代码
  // 公共的初始化代码
  this.userData = getUserData()
   wx.getLocation({
   type: 'wgs84',
   success (res) {
    // 执行 onLoad
    this.lifetimeBackup.onLoad.call(this, options)
   }
  })
 }
 
 // ...

 originPage(config)
}

当然,实际开发过程中的初始化代码不可能这么少,可以用很多方式把它抽离出去,比如这样:

// utils/initial.js
function initial(callback) {
 this.userData = getUserData()
 wx.getLocation({
  type: 'wgs84',
  success (res) {
   callback()
  }
 })
}
 
// utils/wx.js
var initial = require('./initial')
var originPage = Page

function MyPage(config) {
 this.lifetimeBackup = {
  onLoad: config.onLoad
 }
 config.onLoad = function(options) {
  initial(() => {
   this.lifetimeBackup.onLoad.call(this, options)
  })
 }
 // ...
 originPage(config)
}

也可以使用更多高级的方法抽离出去,比如 event bus 之类的,就不多赘述。

看似很简单,但其实这样忽略了一个问题 —— 生命周期顺序被打乱了!如果初始化方法里有异步代码,那首先执行的可能就是 onShow ,而不是约定的 onLoad。

恢复生命周期顺序

为了保证生命周期函数能够按顺序执行,可以先临时清空生命周期函数,然后再依次执行,如下代码所示:

// utils/wx.js
const LIFETIME_EVENTS = ['onLoad', 'onShow', 'onReady']
var initial = require('./initial')
var originPage = Page


function MyPage(config) {
 LIFETIME_EVENTS.forEach((event) => {
  // 备份生命周期函数
  this.lifetimeBackup[event] = config[event]
  // 临时清空
  config[event] = function() {}
 })
 config.onLoad = function(options) {
  initial(() => {
   // 依次执行生命周期函数
   LIFETIME_EVENTS.forEach((event) => {
    this.lifetimeBackup[event].call(this, options)
   })
  })
 }
 // ...
 originPage(config)
}

注意上述代码还是有问题的,当小程序业务跳走再返回或者切后台到前台时,onShow 无法正常触发,因为被设置为空函数了。

为了保证 onShow 等生命周期函数的后续正常运行,需要在依次执行完生命周期函数后,再把它们恢复到 config 下,这是必不可少的。完整代码如下:

// utils/wx.js
const LIFETIME_EVENTS = ['onLoad', 'onShow', 'onReady']
var initial = require('./initial')
var originPage = Page


function MyPage(config) {
 LIFETIME_EVENTS.forEach((event) => {
  // 备份生命周期函数
  this.lifetimeBackup[event] = config[event]
  // 临时清空
  config[event] = function() {}
 })
 config.onLoad = function(options) {
  initial(() => {
   // 依次执行生命周期函数
   LIFETIME_EVENTS.forEach((event) => {
    this.lifetimeBackup[event].call(this, options)
    // 执行完后,恢复过来
    config[event] = this.lifetimeBackup[event]
   })
  })
 }
 // ...
 originPage(config)
}

总结

代理了 onLoad 后,就可以手动控制其执行的时机,可以折腾的事情就多了很多。比如当初始化函数需要执行(请求)的内容比较多,耗时比较长时,可以统一给页面增加一些 loading 提示等。总之,可以自由控制了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery实现心算练习代码
Dec 06 Javascript
JQuery删除DOM节点的方法
Jun 11 Javascript
原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)
Jun 21 Javascript
EasyUI在Panel上动态添加LinkButton按钮
Aug 11 Javascript
基于JavaScript实现报警器提示音效果
Oct 27 Javascript
老生常谈JS中的继承及实现代码
Jul 06 Javascript
vue移动端下拉刷新和上拉加载的实现代码
Sep 08 Javascript
vue中img src 动态加载本地json的图片路径写法
Apr 25 Javascript
微信小程序如何自定义table组件
Jun 29 Javascript
解决vue-cli webpack打包开启Gzip 报错问题
Jul 24 Javascript
对layui初始化列表的CheckBox属性详解
Sep 13 Javascript
微信小程序录音实现功能并上传(使用node解析接收)
Feb 26 Javascript
js canvas实现星空连线背景特效
Nov 01 #Javascript
jQuery鼠标滑过横向时间轴样式(代码详解)
Nov 01 #jQuery
微信小程序定义和调用全局变量globalData的实现
Nov 01 #Javascript
vue-router 中 meta的用法详解
Nov 01 #Javascript
VUE 解决mode为history页面为空白的问题
Nov 01 #Javascript
js+canvas实现两张图片合并成一张图片的方法
Nov 01 #Javascript
JS中自定义事件的使用与触发操作实例分析
Nov 01 #Javascript
You might like
如何让CI框架支持service层
2014/10/29 PHP
php正确输出json数据的实例讲解
2018/08/21 PHP
jquery实现的3D旋转木马特效代码分享
2015/08/25 Javascript
JS实现可点击展开与关闭的左侧广告代码
2015/09/02 Javascript
Ionic快速安装教程
2016/06/03 Javascript
jQuery+koa2实现简单的Ajax请求的示例
2018/03/06 jQuery
微信小程序仿美团城市选择
2018/06/06 Javascript
js实现坦克移动小游戏
2019/10/28 Javascript
jQuery高级编程之js对象、json与ajax用法实例分析
2019/11/01 jQuery
解决vue addRoutes不生效问题
2020/08/04 Javascript
openLayer4实现动态改变标注图标
2020/08/17 Javascript
vue-cli+webpack项目打包到服务器后,ttf字体找不到的解决操作
2020/08/28 Javascript
element-ui tree结构实现增删改自定义功能代码
2020/08/31 Javascript
[02:17]TI4西雅图DOTA2前线报道 啸天mik夫妻档解说
2014/07/08 DOTA
[01:15:56]2018DOTA2亚洲邀请赛3月30日 小组赛A组 TNC VS Newbee
2018/03/31 DOTA
使用PyInstaller将Python程序文件转换为可执行程序文件
2016/07/08 Python
python实现二维码扫码自动登录淘宝
2016/12/27 Python
Python3之文件读写操作的实例讲解
2018/01/23 Python
深入分析python数据挖掘 Json结构分析
2018/04/21 Python
浅析PyTorch中nn.Module的使用
2019/08/18 Python
Python 写了个新型冠状病毒疫情传播模拟程序
2020/02/14 Python
Python使用QQ邮箱发送邮件实例与QQ邮箱设置详解
2020/02/18 Python
Python使用内置函数setattr设置对象的属性值
2020/10/16 Python
CSS3哪些新特性值得称赞
2016/03/02 HTML / CSS
HTML5新增的Css选择器、伪类介绍
2013/08/07 HTML / CSS
世界上第一个水枕头:Mediflow
2018/12/06 全球购物
C#如何判断当前用户是否输入某个域
2015/12/07 面试题
班组长安全职责
2014/01/05 职场文书
个人政风行风自查自纠报告
2014/10/21 职场文书
个园导游词
2015/02/04 职场文书
闪闪的红星观后感
2015/06/08 职场文书
法制教育讲座心得体会
2016/01/14 职场文书
python - timeit 时间模块
2021/04/06 Python
教你如何用python开发一款数字推盘小游戏
2021/04/14 Python
go web 预防跨站脚本的实现方式
2021/06/11 Golang
Android自定义ScrollView实现阻尼回弹
2022/04/01 Java/Android