人活着,總得要點英雄主義的,哪怕失敗、死亡。前端
也許在小程序全部生命週期裏,咱們用的最多的就是 onLoad
,一大堆代碼都要在初始化的時候執行。小程序
不少時候,初始化的代碼是每一個頁面共用的,好比獲取用戶信息、獲取定位等:微信
Page({
onLoad() {
this.userData = getUserData()
wx.getLocation({
type: 'wgs84',
success (res) {
// 業務代碼
// ...
}
})
}
// ...
})
複製代碼
長此以往,每一個頁面的 js 裏都是如上的重複代碼。若是能夠先執行完通用的初始化代碼,再執行每一個頁面各自的 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
。post
爲了保證生命週期函數可以按順序執行,能夠先臨時清空生命週期函數,而後再依次執行,以下代碼所示:ui
// 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
沒法正常觸發,由於被設置爲空函數了。this
爲了保證 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 提示等。總之,能夠自由控制了。
美團單車事業部(摩拜單車)誠招前端 / 小程序研發工程師,位置北京,有興趣能夠發簡歷到 zhangshibing@mobike.com 或者掃二維碼先加微信勾搭:)