详解小程序如何改变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 动态改变图片大小
Jun 11 Javascript
jQuery侧边栏随窗口滚动实现方法
Mar 04 Javascript
jquery实现带单选按钮的表格行选中时高亮显示
Aug 01 Javascript
jquery ready(fn)事件使用介绍
Aug 21 Javascript
javascript结合fileReader 实现上传图片
Jan 30 Javascript
jQuery实现长按按钮触发事件的方法
Feb 02 Javascript
JavaScript获取元素尺寸和大小操作总结
Feb 27 Javascript
基于javascript实现窗口抖动效果
Jan 03 Javascript
node中Express 动态设置端口的方法
Aug 04 Javascript
浅谈express 中间件机制及实现原理
Aug 31 Javascript
vue进入页面时不在顶部,检测滚动返回顶部按钮问题及解决方法
Oct 30 Javascript
JavaScript实现雪花飘落效果
Dec 27 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中time()和mktime()方法的区别
2013/09/28 PHP
浅析Yii2 GridView 日期格式化并实现日期可搜索教程
2016/04/22 PHP
jQuery 美元符冲突的解决方法
2010/03/28 Javascript
基于jquery的网页SELECT下拉框美化代码
2010/10/28 Javascript
推荐30个新鲜出炉的精美 jQuery 效果
2012/03/26 Javascript
jQuery源码中的chunker 正则过滤符分析
2012/07/31 Javascript
JavaScript中的字符串操作详解
2013/11/12 Javascript
JavaScript转换二进制编码为ASCII码的方法
2015/04/16 Javascript
详解jQuery事件
2017/01/13 Javascript
jquery实现input框获取焦点的简单实例
2017/01/26 Javascript
使用重写url机制实现验证码换一张功能
2017/08/01 Javascript
vue2.0 路由不显示router-view的解决方法
2018/03/06 Javascript
js传递数组参数到后台controller的方法
2018/03/29 Javascript
解决vue-router在同一个路由下切换,取不到变化的路由参数问题
2018/09/01 Javascript
vue百度地图 + 定位的详解
2019/05/13 Javascript
vue回到顶部监听滚动事件详解
2019/08/02 Javascript
JointJS JavaScript流程图绘制框架解析
2019/08/15 Javascript
python获得图片base64编码示例
2014/01/16 Python
在RedHat系Linux上部署Python的Celery框架的教程
2015/04/07 Python
python 类详解及简单实例
2017/03/24 Python
tensorflow 保存模型和取出中间权重例子
2020/01/24 Python
python如何保存文本文件
2020/06/07 Python
python字典的值可以修改吗
2020/06/29 Python
深入了解Python enumerate和zip
2020/07/16 Python
纯css3使用vw和vh实现自适应的方法
2018/02/09 HTML / CSS
整理HTML5中表单的常用属性及新属性
2016/02/19 HTML / CSS
adidas马来西亚官网:adidas MY
2020/09/12 全球购物
值传递还是引用传递
2015/02/08 面试题
大学生个人总结的自我评价
2013/10/05 职场文书
日语专业个人求职信范文
2014/02/02 职场文书
利群广告词
2014/03/20 职场文书
2015年植树节活动总结
2015/02/06 职场文书
债务纠纷起诉书
2015/05/20 职场文书
用Python爬取英雄联盟的皮肤详细示例
2021/12/06 Python
你需要掌握的20个Python常用技巧
2022/02/28 Python
Java实现简单小画板
2022/06/10 Java/Android