详解小程序如何改变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 相关文章推荐
JQuery 绑定select标签的onchange事件,弹出选择的值,并实现跳转、传参
Jan 06 Javascript
jQuery中 prop() attr()使用详解
May 19 Javascript
js实现select跳转菜单新窗口效果代码分享(超简单)
Aug 21 Javascript
详解Javascript事件驱动编程
Jan 03 Javascript
Sea.JS知识总结
May 05 Javascript
Js+Ajax,Get和Post在使用上的区别小结
Jun 08 Javascript
javascript时间差插件分享
Jul 18 Javascript
JavaScript中Array的实用操作技巧分享
Sep 11 Javascript
微信小程序实现折叠面板
Jan 31 Javascript
Angularjs之ngModel中的值验证绑定方法
Sep 13 Javascript
mpvue实现左侧导航与右侧内容的联动
Oct 21 Javascript
jQuery实现移动端扭蛋机抽奖
Nov 08 jQuery
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+redis消息队列实现抢购功能
2018/02/08 PHP
PHP实现获取url地址中顶级域名的方法示例
2019/06/05 PHP
Laravel 类和接口注入相关的代码
2019/10/15 PHP
JavaScript使用prototype定义对象类型
2007/02/07 Javascript
一个简单的JavaScript数据缓存系统实现代码
2010/10/24 Javascript
ASP.NET jQuery 实例11 通过使用jQuery validation插件简单实现用户登录页面验证功能
2012/02/03 Javascript
JQuery DataTable删除行后的页面更新利用Ajax解决
2013/05/17 Javascript
jquery实现简单的拖拽效果实例兼容所有主流浏览器(优化篇)
2013/06/28 Javascript
jquery实现不同大小浏览器使用不同的css样式表的方法
2014/04/02 Javascript
更快的异步执行(setTimeout多浏览器)
2014/08/12 Javascript
jQuery中extend函数详解
2015/02/13 Javascript
js检测iframe是否加载完成的方法
2015/11/26 Javascript
详解AngularJS过滤器的使用
2016/03/11 Javascript
javascript和jQuery实现网页实时聊天的ajax长轮询
2016/07/20 Javascript
JS基于递归算法实现1,2,3,4,5,6,7,8,9倒序放入数组中的方法
2017/01/03 Javascript
详解能在多种前端框架下使用的表格控件
2017/01/11 Javascript
jQuery为DOM动态追加事件的方法
2017/02/16 Javascript
Vue.js如何优雅的进行form validation
2017/04/07 Javascript
微信小程序如何自定义table组件
2019/06/29 Javascript
[39:53]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第一场 11.19
2020/11/19 DOTA
Python中使用第三方库xlrd来写入Excel文件示例
2015/04/05 Python
基于Python实现迪杰斯特拉和弗洛伊德算法
2020/05/27 Python
python3.7 使用pymssql往sqlserver插入数据的方法
2019/07/08 Python
Python3实现将一维数组按标准长度分隔为二维数组
2019/11/29 Python
CSS3 box-sizing属性详解
2016/11/15 HTML / CSS
如何用canvas实现在线签名的示例代码
2018/07/10 HTML / CSS
大女孩胸罩:Big Girls Bras
2016/12/15 全球购物
Hoka One One法国官网:美国专业跑鞋品牌
2018/12/29 全球购物
开普敦通行证:Cape Town Pass
2019/07/18 全球购物
写一个函数返回1+2+3+…+n的值(假定结果不会超过长整型变量的范围)
2014/09/05 面试题
公务员培训心得体会
2013/12/28 职场文书
综合实践活动方案
2014/02/14 职场文书
终止劳动合同协议书
2014/10/05 职场文书
交通事故协议书范本
2014/11/18 职场文书
从贫穷到富有,是知识技能和学习力的差别
2019/08/20 职场文书
导游词之无锡梅园
2019/11/28 职场文书