人活着,總得要點英雄主義的,哪怕失敗、死亡。
也許在小程序全部生命週期裏,咱們用的最多的就是 onLoad
,一大堆代碼都要在初始化的時候執行。小程序
不少時候,初始化的代碼是每一個頁面共用的,好比獲取用戶信息、獲取定位等:異步
Page({ onLoad() { this.userData = getUserData() wx.getLocation({ type: 'wgs84', success (res) { // 業務代碼 // ... } }) } // ... })
長此以往,每一個頁面的 js 裏都是如上的重複代碼。若是能夠先執行完通用的初始化代碼,再執行每一個頁面各自的 onLoad
多好,惋惜小程序並無提供相似的鉤子函數,那就本身來吧。函數
按照前幾篇的方法,能夠代理原有的 onLoad
事件:ui
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) }
固然,實際開發過程當中的初始化代碼不可能這麼少,能夠用不少方式把它抽離出去,好比這樣:this
// 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 之類的,就很少贅述。spa
看似很簡單,但其實這樣忽略了一個問題 —— 生命週期順序被打亂了!若是初始化方法裏有異步代碼,那首先執行的可能就是 onShow
,而不是約定的 onLoad
。代理
爲了保證生命週期函數可以按順序執行,能夠先臨時清空生命週期函數,而後再依次執行,以下代碼所示:code
// 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
沒法正常觸發,由於被設置爲空函數了。blog
爲了保證 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 提示等。總之,能夠自由控制了。