详解小程序如何改变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学习历程和心得小结
Aug 16 Javascript
javascript学习笔记(二十) 获得和设置元素的特性(属性)
Jun 20 Javascript
jquery 淡入淡出效果的简单实现
Feb 07 Javascript
jQuery选择器源码解读(七):elementMatcher函数
Mar 31 Javascript
Javascript控制div属性动态变化实例分析
Oct 08 Javascript
基于jquery实现省市联动特效
Dec 17 Javascript
详解JS正则replace的使用方法
Mar 06 Javascript
javascript实现的猜数小游戏完整实例代码
May 10 Javascript
javascript基础知识
Jun 07 Javascript
详解vue-router 动态路由下子页面多页共活的解决方案
Dec 22 Javascript
Ant-design-vue Table组件customRow属性的使用说明
Oct 28 Javascript
Vue如何实现验证码输入交互
Dec 07 Vue.js
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
人人网javascript面试题 可以提前实现下
2012/01/05 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
2014/02/22 Javascript
js实现连个数字相加而不是拼接的方法
2014/02/23 Javascript
js冒泡、捕获事件及阻止冒泡方法详细总结
2014/05/08 Javascript
AngularJS学习笔记之ng-options指令
2015/06/16 Javascript
Json对象和字符串互相转换json数据拼接和JSON使用方式详细介绍(小结)
2016/10/25 Javascript
jquery 追加元素append、prepend、before、after用法与区别分析
2016/12/02 Javascript
underscore之Collections_动力节点Java学院整理
2017/07/10 Javascript
基于JavaScript实现图片连播和联级菜单实例代码
2017/07/28 Javascript
Vue-router路由判断页面未登录跳转到登录页面的实例
2017/10/26 Javascript
浅谈vue项目重构技术要点和总结
2018/01/23 Javascript
vue下使用nginx刷新页面404的问题解决
2019/08/02 Javascript
Vue ​v-model相关知识总结
2021/01/28 Vue.js
初步认识Python中的列表与位运算符
2015/10/12 Python
浅谈Python浅拷贝、深拷贝及引用机制
2016/12/15 Python
Pycharm学习教程(4) Python解释器的相关配置
2017/05/03 Python
Python实现购物车功能的方法分析
2017/11/10 Python
利用Python代码实现数据可视化的5种方法详解
2018/03/25 Python
PyTorch读取Cifar数据集并显示图片的实例讲解
2018/07/27 Python
python实现贪吃蛇游戏
2020/03/21 Python
Python实现线性插值和三次样条插值的示例代码
2019/11/13 Python
Python Opencv中用compareHist函数进行直方图比较对比图片
2020/04/07 Python
美国受信赖的教育产品供应商:Nest Learning
2018/06/14 全球购物
意大利顶级奢侈品电商:LUISAVIAROMA(支持中文)
2020/05/26 全球购物
应届毕业生个人自荐信范文
2013/11/30 职场文书
团员的自我评价
2013/12/01 职场文书
财务方面个人工作的自我评价
2013/12/28 职场文书
安全检查与奖惩制度
2014/01/23 职场文书
酒店节能降耗方案
2014/05/08 职场文书
幼儿园六一儿童节活动方案
2014/08/26 职场文书
2014和解协议书范文
2014/09/15 职场文书
应急管理工作总结2015
2015/05/04 职场文书
2015年社区科普工作总结
2015/05/13 职场文书
2016优秀护士求职自荐信
2016/01/28 职场文书
Python采集爬取京东商品信息和评论并存入MySQL
2022/04/12 Python
oracle数据库去除重复数据
2022/05/20 Oracle