详解小程序如何改变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方法和技巧大全
Dec 27 Javascript
JavaScript入门教程(7) History历史对象
Jan 31 Javascript
将CKfinder整合进CKEditor3.0的新方法
Jan 10 Javascript
jQuery结合CSS制作动态的下拉菜单
Oct 27 Javascript
jquery实现简单的遮罩层
Jan 08 Javascript
JavaScript实现带播放列表的音乐播放器实例分享
Mar 07 Javascript
原生JavaScript实现Ajax异步请求
Nov 19 Javascript
vue分页插件的使用方法
Dec 25 Javascript
vue自定义标签和单页面多路由的实现代码
May 03 Javascript
微信小程序国际化探索实现(附源码地址)
May 20 Javascript
Vue 电商后台管理项目阶段性总结(推荐)
Aug 22 Javascript
ant design vue嵌套表格及表格内部编辑的用法说明
Oct 28 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
基于pear auth实现登录验证
2010/02/26 PHP
有关PHP中MVC的开发经验分享
2012/05/17 PHP
php上传文件,创建递归目录的实例代码
2013/10/18 PHP
PHP 使用pcntl和libevent 实现Timer功能
2013/10/27 PHP
php实现的太平洋时间和北京时间互转的自定义函数分享
2014/08/19 PHP
php简单实现屏蔽指定ip段用户的访问
2015/04/29 PHP
php中str_pad()函数用法分析
2017/03/28 PHP
PHP网站自动化配置的实现方法(必看)
2017/05/27 PHP
基于laravel Request的所有方法详解
2019/09/29 PHP
JS 对象介绍
2010/01/20 Javascript
使用JavaScript switch case 另类写法
2010/03/14 Javascript
纯js实现背景图片切换效果代码
2010/11/14 Javascript
使用javascript:将其它类型值转换成布尔类型值的解决方法详解
2013/05/07 Javascript
js判断undefined变量类型使用typeof
2013/06/03 Javascript
React props和state属性的具体使用方法
2018/04/12 Javascript
nuxt.js 在middleware(中间件)中实现路由鉴权操作
2020/11/06 Javascript
[56:24]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#1Liquid VS MVP.Phx第二局
2016/03/04 DOTA
对于Python异常处理慎用“except:pass”建议
2015/04/02 Python
Python GUI Tkinter简单实现个性签名设计
2018/06/19 Python
利用Python将文本中的中英文分离方法
2018/10/31 Python
Python unittest 简单实现参数化的方法
2018/11/30 Python
python分割一个文本为多个文本的方法
2019/07/22 Python
python连接PostgreSQL数据库的过程详解
2019/09/18 Python
解决pymysql cursor.fetchall() 获取不到数据的问题
2020/05/15 Python
Python基于Twilio及腾讯云实现国际国内短信接口
2020/06/18 Python
如何用Anaconda搭建虚拟环境并创建Django项目
2020/08/02 Python
python模拟点击玩游戏的实例讲解
2020/11/26 Python
手把手教你实现一个canvas智绘画板的方法
2019/03/04 HTML / CSS
香港卓悦化妆品官网:BONJOUR
2017/09/21 全球购物
Michael Kors澳大利亚官网:世界知名的奢侈饰品和成衣设计师
2020/02/13 全球购物
学术会议主持词
2014/03/17 职场文书
党员群众路线自我剖析材料
2014/10/06 职场文书
总经理司机岗位职责
2015/04/10 职场文书
网络销售员岗位职责
2015/04/11 职场文书
2015年社区居委会工作总结
2015/05/18 职场文书
为什么不建议在go项目中使用init()
2021/04/12 Golang