详解小程序如何改变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获取ASP.NET服务器端控件dropdownlist和radiobuttonlist生成客户端HTML标签后的value和text值
Jun 28 Javascript
深入理解JSON数据源格式
Jan 10 Javascript
jQuery过滤选择器:not()方法使用介绍
Apr 20 Javascript
js实现文章文字大小字号功能完整实例
Nov 01 Javascript
Javascript学习笔记之函数篇(四):arguments 对象
Nov 23 Javascript
JQuery插入DOM节点的方法
Jun 11 Javascript
JQuery标签页效果实例详解
Dec 24 Javascript
详解Javacript和AngularJS中的Promises
Feb 09 Javascript
js 倒计时(高效率服务器时间同步)
Sep 12 Javascript
vue中的模态对话框组件实现过程
May 01 Javascript
Vue脚手架的简单使用实例
Jul 10 Javascript
JSONP解决JS跨域问题的实现
May 25 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
我的群发邮件程序
2006/10/09 PHP
详解PHP显示MySQL数据的三种方法
2008/06/05 PHP
免费的ip数据库淘宝IP地址库简介和PHP调用实例
2014/04/08 PHP
Javascript 两个窗体之间传值实现代码
2009/09/25 Javascript
基于jQuery实现复选框的全选 全不选 反选功能
2014/11/24 Javascript
Javascript进制转换实例分析
2015/05/14 Javascript
深入分析jQuery的ready函数是如何工作的(工作原理)
2015/12/17 Javascript
javascript实现的猜数小游戏完整实例代码
2016/05/10 Javascript
[原创]Javascript 实现广告后加载 可加载百度谷歌联盟广告
2016/05/11 Javascript
javascript实现的全国省市县无刷新多级关联菜单效果代码
2016/08/01 Javascript
js 基础篇必看(点击事件轮播图的简单实现)
2016/08/20 Javascript
js当前页面登录注册框,固定div,底层阴影的实例代码
2016/10/04 Javascript
js微信支付实现代码
2016/12/22 Javascript
详解webpack3如何正确引用并使用jQuery库
2017/08/26 jQuery
从setTimeout看js函数执行过程
2017/12/19 Javascript
nodejs中函数的调用实例详解
2018/10/31 NodeJs
vue请求本地自己编写的json文件的方法
2019/04/25 Javascript
jQuery表单选择器用法详解
2019/08/22 jQuery
NodeJS有难度的面试题(能答对几个)
2019/10/09 NodeJs
深入理解redux之compose的具体应用
2020/01/12 Javascript
python调用百度语音REST API
2018/08/30 Python
Python numpy矩阵处理运算工具用法汇总
2020/07/13 Python
Python 用__new__方法实现单例的操作
2020/12/11 Python
详解appium自动化测试工具(monitor、uiautomatorviewer)
2021/01/27 Python
使用C#编写创建一个线程的代码
2013/01/22 面试题
组织鉴定材料
2014/06/02 职场文书
校长创先争优承诺书
2014/08/30 职场文书
综合素质评价思想道德自我评价
2015/03/09 职场文书
拖欠货款起诉状
2015/05/20 职场文书
傅雷家书读书笔记
2015/06/29 职场文书
老人院义工活动感想
2015/08/07 职场文书
公司年会晚会开幕词
2019/04/02 职场文书
幼儿教师三分钟演讲稿
2019/06/21 职场文书
解决tk mapper 通用mapper的bug问题
2021/06/16 Java/Android
使用CSS实现一个搜索引擎的原理解析
2021/09/25 HTML / CSS
Redis实现短信验证码登录的示例代码
2022/06/14 Redis