详解小程序如何改变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 相关文章推荐
用js实现的页面关键字密度查询代码
Dec 27 Javascript
Mootools 1.2教程 输入过滤第二部分(字符串)
Sep 15 Javascript
快速学习jQuery插件 Form表单插件使用方法
Dec 01 Javascript
浅析Bootstrap表格的使用
Jun 23 Javascript
对js中回调函数的一些看法
Aug 29 Javascript
VUE中的无限循环代码解析
Sep 22 Javascript
JavaScript实现微信号随机切换代码
Mar 09 Javascript
Node.js中的cluster模块深入解读
Jun 11 Javascript
详解Vue调用手机相机和相册以及上传
May 05 Javascript
深入了解Vue动态组件和异步组件
Jan 26 Vue.js
微信小程序中wxs文件的一些妙用分享
Feb 18 Javascript
JavaScript前端面试扁平数据转tree与tree数据扁平化
Jun 14 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
BBS(php & mysql)完整版(八)
2006/10/09 PHP
php连接oracle数据库及查询数据的方法
2014/12/29 PHP
PHP实现十进制数字与二十六进制字母串相互转换操作示例
2018/08/10 PHP
php设计模式之工厂模式用法经典实例分析
2019/09/20 PHP
Javascript 代码也可以变得优美的实现方法
2009/06/22 Javascript
javascript学习笔记(一) 在html中使用javascript
2012/06/18 Javascript
IE6下javasc#ipt:void(0) 无效的解决方法
2013/12/23 Javascript
js判断为空Null与字符串为空简写方法
2014/02/24 Javascript
JavaScript中的Math.E属性使用详解
2015/06/12 Javascript
js中 javascript:void(0) 用法详解
2015/08/11 Javascript
vue插件tab选项卡使用小结
2016/10/27 Javascript
jQuery实现文件编码成base64并通过AJAX上传的方法
2018/04/12 jQuery
使用vue2.0创建的项目的步骤方法
2018/09/25 Javascript
jQuery内容过滤选择器与子元素过滤选择器用法实例分析
2019/02/20 jQuery
JS div匀速移动动画与变速移动动画代码实例
2019/03/26 Javascript
vue 实现模糊检索并根据其他字符的首字母顺序排列
2019/09/19 Javascript
Vue中使用matomo进行访问流量统计的实现
2019/11/05 Javascript
JavaScript实现拖拽盒子效果
2020/02/06 Javascript
js实现树形数据转成扁平数据的方法示例
2020/02/27 Javascript
python抓取网页中的图片示例
2014/02/28 Python
python连接mysql调用存储过程示例
2014/03/05 Python
python从入门到精通(DAY 2)
2015/12/20 Python
python实现中文转换url编码的方法
2016/06/14 Python
Python下的Softmax回归函数的实现方法(推荐)
2017/01/26 Python
python特性语法之遍历、公共方法、引用
2018/08/08 Python
Python 实现域名解析为ip的方法
2019/02/14 Python
python中import与from方法总结(推荐)
2019/03/21 Python
Pytorch基本变量类型FloatTensor与Variable用法
2020/01/08 Python
Python logging模块写入中文出现乱码
2020/05/21 Python
python实现暗通道去雾算法的示例
2020/09/27 Python
HMV日本官网:全球知名的音乐、DVD和电脑游戏零售巨头
2016/08/13 全球购物
护理专业个人求职简历的自我评价
2013/10/13 职场文书
计算机专业毕业生自荐信范文
2014/03/06 职场文书
实习协议书范本
2014/04/22 职场文书
2014年药店工作总结
2014/11/20 职场文书
电子表的操作介绍说明书
2019/10/28 职场文书