微信小程序重写Page函数,实现全局日志记录
概述在上一篇《微信小程序实现类似Vue的全局路由,实现日志记录》中,通过重写wx.navigateTo,wx.switchTab,wx.navigateBack这三个方法实现类似全局路由的功能,但重写这三个方法后仍有一些局限性,无法拦截底部tab的点击事件和安卓手机的物理返回键的返回事件。如果不需要在跳转前进行拦截,那么有一个更好的方案,重写Page函数。解决方案新建myPage....
概述
在上一篇《微信小程序实现类似Vue的全局路由,实现日志记录》中,通过重写wx.navigateTo,wx.switchTab,wx.navigateBack这三个方法实现类似全局路由的功能,但重写这三个方法后仍有一些局限性,无法拦截底部tab的点击事件和安卓手机的物理返回键的返回事件。
如果不需要在跳转前进行拦截,那么有一个更好的方案,重写Page函数。
解决方案
新建myPage.js文件,代码如下:
let data
// 这里data从app.js中传入,为了获取data的一些参数
function init(_data) {
data = _data
// 重写page函数,增加阿里云监控和日志记录
let oldPage = Page
Page = function(obj) {
// 重写onShow方法,用一个变量保存旧的onShow函数
let oldOnShow = obj.onShow
obj.onShow = function() {
enterPageLog()
// 此处不能写成oldOnShow(),否则没有this,this.setData等方法为undefined。这里的this在Page构造函数实例化的时候才会指定
// 在Page构造函数实例化的时候,小程序会将当前的Page对象的原型链(__proto__)增加很多方法,例如setData。当前的obj没有setData
// 上面一段是我猜的
oldOnShow.call(this)
}
// 重写onHide方法,用一个变量保存旧的onHide函数
let oldOnHide = obj.onHide
obj.onHide = function() {
leavePageLog()
// 此处不能写成oldOnHide(),否则没有this,this.setData等方法为undefined。这里的this在Page对象实例化的时候才会指定
oldOnHide.call(this)
}
return oldPage(Monitor.hookPage(obj))
}
}
将这一串代码封在一个js文件中,然后在app.js中引入,在app.js的onLaunch方法中调用该init方法。
import myPage from '/utils/myPage'
App({
data: {},
onLaunch: function() {
// 重写page函数
myPage.init(this.data)
},
...
})
以上代码中,
enterPageLog()和leavePageLog()是为了记录日志,这样就实现了公共的日志记录,不需要在每个页面写重复的记录日志的代码。
Monitor.hookPage(obj)是阿里云的前端监控,官方的方案是在每个Page函数的传参对象包一层,如下:
Page(Monitor.hookPage(options));
重写Page后,不必要在每个Page对象都加这一串。
关键代码解读
let oldOnShow = obj.onShow
obj.onShow = function() {
enterPageLog()
oldOnShow.call(this)
}
重写onShow函数,做完自定义事情,调用旧的onShow函数时,不能写成oldOnShow()。若写成oldOnShow(),在运行时会报错,this.setData、this.createSelectorQuery等方法为undefined。
原因是在app的onLaunch方法中,传入Page函数的对象还没有setData等方法,就是以上代码onShow中的this,也就是obj。在Page构造函数实例化的时候,小程序会将当前的Page函数的原型链(prototype)增加很多方法,例如setData。可以查看这一篇《从源码看微信小程序启动过程》了解小程序启动和加载各对象的过程。
此处使用 oldOnShow.call(this) 来延迟指定this,这个this只有在Page实例化的时候才会指定,也就是上面说的Page实例化后增加了很多方法的this。这就避开了当前Page没有setData、createSelectorQuery等方法的问题。call的原理和用法可以查看这一篇《深入理解JavaScript中的Call、Apply、This》。
结论
这里只是实现了简单的日志记录功能,通过重写Page,也可以实现其他一些公共功能,包括增加公共函数、参数、事件,权限判断等。
JS语言的特性可以重写很多原生的或者系统的方法,合理的重写可以实现很多公共的功能,减少开发量。
更多推荐
所有评论(0)