详解小程序如何改变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阻止冒泡事件以及默认事件发生的简单方法
Jan 17 Javascript
js监听鼠标点击和键盘点击事件并自动跳转页面
Sep 24 Javascript
javascript实现Table间隔色以及选择高亮(和动态切换数据)的方法
May 14 Javascript
jQuery实现简单的文件上传进度条效果
Mar 26 Javascript
最简单纯JavaScript实现Tab标签页切换的方式(推荐)
Jul 25 Javascript
js方法数据验证的简单实例
Sep 17 Javascript
详解打造 Vue.js 可复用组件
Mar 24 Javascript
Webpack中css-loader和less-loader的使用教程
Apr 27 Javascript
JS遍历DOM文档树的方法实例详解
Apr 03 Javascript
基于vue通用表单解决方案的思考与分析
Mar 16 Javascript
vue 使用 vue-pdf 实现pdf在线预览的示例代码
Apr 26 Javascript
避坑之 JavaScript 中的toFixed()和正则表达式
Apr 19 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为php增加openssl模块的方法
2011/06/14 PHP
PHP实现生成唯一会员卡号
2015/08/24 PHP
thinkPHP框架中执行原生SQL语句的方法
2017/10/25 PHP
PHP实现字符串的全排列详解
2019/04/24 PHP
php-7.3.6 编译安装过程
2020/02/11 PHP
javascript String 的扩展方法集合
2008/06/01 Javascript
JSON 和 JavaScript eval使用说明
2010/06/13 Javascript
javascript检测对象中是否存在某个属性判断方法小结
2013/05/19 Javascript
解决js中window.open弹出的是上次的缓存页面问题
2013/12/29 Javascript
jquery获取颜色在ie和ff下的区别示例介绍
2014/03/28 Javascript
js实现特定位取反原理及示例
2014/06/30 Javascript
微信小程序 实现拖拽事件监听实例详解
2016/11/16 Javascript
浅谈Node.js:Buffer模块
2016/12/05 Javascript
jQuery.Form实现Ajax上传文件同时设置headers的方法
2017/06/26 jQuery
解决IE7中使用jQuery动态操作name问题
2017/08/28 jQuery
JS实现快速比较两个字符串中包含有相同数字的方法
2017/09/11 Javascript
使用vue-cli(vue脚手架)快速搭建项目的方法
2018/05/21 Javascript
vue 巧用过渡效果(小结)
2018/09/22 Javascript
javascript删除数组元素的七个方法示例
2019/09/09 Javascript
解决vue-cli项目开发运行时内存暴涨卡死电脑问题
2019/10/29 Javascript
Vue 中使用 typescript的方法详解
2020/02/17 Javascript
python版本的读写锁操作方法
2016/04/25 Python
Python3.5迭代器与生成器用法实例分析
2019/04/30 Python
Python中six模块基础用法
2019/12/08 Python
QML实现钟表效果
2020/06/02 Python
使用python实现下载我们想听的歌曲,速度超快
2020/07/09 Python
CSS3解析抖音LOGO制作的方法步骤
2019/04/11 HTML / CSS
lululemon美国官网:瑜伽服+跑步装备
2018/11/16 全球购物
英国鹦鹉店:Parrot Essentials
2018/12/03 全球购物
巴黎欧莱雅法国官网:L’Oreal Paris
2019/04/30 全球购物
Nike澳大利亚官网:Nike.com (AU)
2019/06/03 全球购物
多媒体专业自我鉴定
2014/02/28 职场文书
幼儿园安全教育月活动总结
2015/05/08 职场文书
导游词之杭州岳王庙
2019/11/13 职场文书
go语言中切片与内存复制 memcpy 的实现操作
2021/04/27 Golang
Java练习之潜艇小游戏的实现
2022/03/16 Java/Android