详解小程序如何改变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 相关文章推荐
JavaScript 数组运用实现代码
Apr 13 Javascript
用JQuery实现全选与取消的两种简单方法
Feb 22 Javascript
jquery高级编程的最佳实践详解
Mar 23 Javascript
基于jQuery实现下拉框
Nov 24 Javascript
JavaScript中的null和undefined区别介绍
Jan 01 Javascript
JavaScript使用Prototype实现面向对象的方法
Apr 14 Javascript
jQuery+ajax+asp.net获取Json值的方法
Jun 08 Javascript
JavaScript实现的超简单计算器功能示例
Dec 23 Javascript
JavaScript 中的12种循环遍历方法【总结】
May 31 Javascript
微信小程序webview 脚手架使用详解
Jul 22 Javascript
JavaScript创建表格的方法
Apr 13 Javascript
vue 自定指令生成uuid滚动监听达到tab表格吸顶效果的代码
Sep 16 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
使用PHP批量生成随机用户名
2008/07/10 PHP
php相当简单的分页类
2008/10/02 PHP
php实现文件下载功能的几个代码分享
2014/05/10 PHP
mac环境中使用brew安装php5.5.15
2014/08/18 PHP
php实现的双向队列类实例
2014/09/24 PHP
php提示Failed to write session data错误的解决方法
2014/12/17 PHP
php实现utf-8转unicode函数分享
2015/01/06 PHP
微信公众平台开发之配置与请求
2015/08/26 PHP
php的无刷新操作实现方法分析
2020/02/28 PHP
thinkphp框架实现路由重定义简化url访问地址的方法分析
2020/04/04 PHP
javascript showModalDialog 多层模态窗口实现页面提交及刷新的代码
2009/11/28 Javascript
jQuery cdn使用介绍
2013/05/08 Javascript
仿百度输入框智能提示的js代码
2013/08/22 Javascript
浅谈JavaScript中的字符编码转换问题
2015/07/07 Javascript
javascript中setAttribute()函数使用方法及兼容性
2015/07/19 Javascript
JS获取时间的相关函数及时间戳与时间日期之间的转换
2016/02/04 Javascript
jQuery基于BootStrap样式实现无限极地区联动
2016/08/26 Javascript
jQuery得到多个值只能用取Class ,不能用取ID的方法
2016/12/04 Javascript
浅谈jQuery的bind和unbind事件(绑定和解绑事件)
2017/03/02 Javascript
浅谈angularjs依赖服务注入写法的注意点
2017/04/24 Javascript
基于AngularJS的拖拽文件上传的实例代码
2017/07/15 Javascript
vue实现样式之间的切换及vue动态样式的实现方法
2017/12/19 Javascript
vue项目中axios请求网络接口封装的示例代码
2018/12/18 Javascript
微信小程序学习总结(五)常见问题实例小结
2020/06/04 Javascript
js实现微信聊天界面
2020/08/09 Javascript
[37:22]DOTA2上海特级锦标赛D组资格赛#2 Liquid VS VP第一局
2016/02/28 DOTA
python编程测试电脑开启最大线程数实例代码
2018/02/09 Python
Python通过属性手段实现只允许调用一次的示例讲解
2018/04/21 Python
python可视化实现代码
2019/01/15 Python
python的debug实用工具 pdb详解
2019/07/12 Python
python实现的Iou与Giou代码
2020/01/18 Python
Python+unittest+requests 接口自动化测试框架搭建教程
2020/10/09 Python
利用CSS3实现圆角的outline效果的教程
2015/06/05 HTML / CSS
哈理工毕业生的求职信
2013/12/22 职场文书
应聘销售主管的求职信
2014/04/26 职场文书
Python实现位图分割的效果
2021/11/20 Python