详解小程序如何改变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 面向对象 重载
May 13 Javascript
jquery制作select列表双向选择示例代码
Sep 02 Javascript
简易的投票系统以及js刷票思路和方法
Apr 07 Javascript
详解maxlength属性在textarea里奇怪的表现
Dec 27 Javascript
jquery中cookie用法实例详解(获取,存储,删除等)
Jan 04 Javascript
JS实现图片平面旋转的方法
Mar 01 Javascript
Bootstrap基本组件学习笔记之input输入框组(9)
Dec 07 Javascript
js实现兼容PC端和移动端滑块拖动选择数字效果
Feb 16 Javascript
three.js中文文档学习之创建场景
Nov 20 Javascript
vue-cli2 构建速度优化的实现方法
Jan 08 Javascript
vue3.0 搭建项目总结(详细步骤)
May 20 Javascript
详解vue 组件的实现原理
Nov 12 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
回首过去10年中最搞笑的10部动漫,哪一部让你节操尽碎?
2020/03/03 日漫
sony ICF-2010 拆解与改装
2021/03/02 无线电
php ftp文件上传函数(基础版)
2010/06/03 PHP
mysql数据库差异比较的PHP代码
2012/02/05 PHP
php设置编码格式的方法
2013/03/05 PHP
Laravel框架中VerifyCsrfToken报错问题的解决
2017/08/30 PHP
一些不错的js函数ajax
2008/08/20 Javascript
js弹出层包含flash 不能关闭隐藏的2种处理方法
2013/06/17 Javascript
Js,alert出现乱码问题的解决方法
2013/06/19 Javascript
js 实现 input type="file" 文件上传示例代码
2013/08/07 Javascript
Javascript浮点数乘积运算出现多位小数的解决方法
2014/02/17 Javascript
jquery.cookie.js使用指南
2015/01/05 Javascript
Vue自定义指令拖拽功能示例
2017/02/17 Javascript
基于ExtJs在页面上window再调用Window的事件处理方法
2017/07/26 Javascript
NodeJS安装图文教程
2018/04/19 NodeJs
JS中的算法与数据结构之栈(Stack)实例详解
2019/08/20 Javascript
JS中类的静态方法,静态变量,实例方法,实例变量区别与用法实例分析
2020/03/14 Javascript
如何解决jQuery 和其他JS库的冲突
2020/06/22 jQuery
JavaScript 实现拖拽效果组件功能(兼容移动端)
2020/11/11 Javascript
Python学习笔记之os模块使用总结
2014/11/03 Python
Python 快速实现CLI 应用程序的脚手架
2017/12/05 Python
Python 绘制酷炫的三维图步骤详解
2019/07/12 Python
python Django框架实现web端分页呈现数据
2019/10/31 Python
代码总结Python2 和 Python3 字符串的区别
2020/01/28 Python
python爬虫模块URL管理器模块用法解析
2020/02/03 Python
Python下载的11种姿势(小结)
2020/11/18 Python
python向xls写入数据(包括合并,边框,对齐,列宽)
2021/02/02 Python
基于CSS3的animation属性实现微信拍一拍动画效果
2020/06/22 HTML / CSS
Perry Ellis官网:美国男士品味服装
2016/12/09 全球购物
介绍一下linux的文件系统
2012/03/20 面试题
行政助理工作职责范本
2014/03/04 职场文书
公司领导班子对照检查存在问题整改措施
2014/10/02 职场文书
python opencv常用图形绘制方法(线段、矩形、圆形、椭圆、文本)
2021/04/12 Python
Mysql文件存储图文详解
2021/06/01 MySQL
Java内存模型之happens-before概念详解
2021/06/13 Java/Android
「偶像大师 MILLION LIVE!」七尾百合子手办开订
2022/03/21 日漫