原因
在开发中有个需求,要统计用户在每个页面的访问量,和停留时间。这个在Vue项目中很好实现,利用全局路由,在router的beforeEach方法和afterEach方法中做事情就可以了。
但小程序中没有全局路由,又不想在每个页面的onShow和onHide中写重复代码,该怎么实现呢?
解决方案
先说明这个解决方案没有完美的解决,还是有些问题,有部分问题没法解决。
方法就是重写微信的三个方法,wx.navigateTo,wx.switchTab,wx.navigateBack,这三个方法分别对应跳转页面、切换tab、返回上一页三个功能,在这三个方法中调用后端接口,记录访问日志。
首先是重写wx.navigateTo方法,因为该方法接收一个url参数,而url可能是 / 开头, ./ 开头, ../开头,还需要去掉url上的参数,需要做一些处理。
function rewriteNavigateTo() {
let oldNavigateTo = wx.navigateTo
wx.navigateTo = function(obj) {
let pages = getCurrentPages()
// pages为空则不做处理
if (pages.length === 0) {
oldNavigateTo(obj)
return
}
let leavePath = pages[pages.length - 1].__route__
// 拼接跳转路径
let enterPath = obj.url
// 去除.html
if (enterPath.indexOf('.html') != -1) {
enterPath = enterPath.substr(0, obj.url.indexOf('.html'))
}
// 去除链接参数
if (enterPath.indexOf('?') != -1) {
enterPath = enterPath.substr(0, obj.url.indexOf('?'))
}
// 去除 ../../
let tempPath = leavePath
tempPath = tempPath.substr(0, tempPath.lastIndexOf('/') + 1)
while (true) {
if (enterPath.startsWith('../')) {
enterPath = enterPath.substr(3)
tempPath = tempPath.substr(0, tempPath.length - 1)
tempPath = tempPath.substr(0, tempPath.lastIndexOf('/') + 1)
} else {
break
}
}
// 去除 ./
if (enterPath.startsWith('./')) {
enterPath = enterPath.substr(2)
}
// /开头
if (enterPath.startsWith('/')) {
tempPath = ''
}
enterPath = tempPath + enterPath
obj.success = function(res) {
//进入新页面记录日志
enterPageLog(enterPath)
}
//跳转
oldNavigateTo(obj)
}
}
重写wx.switchTab方法
function rewriteSwitchTab() {
let oldSwitchTab = wx.switchTab
wx.switchTab = function(obj) {
let pages = getCurrentPages()
let leavePath = ''
if(pages.length>0){
leavePath = pages[pages.length - 1].__route__
}
//离开页面记录日志
if (!tabPathSet.has(leavePath)) {
leavePageLog(leavePath)
}
//跳转
oldSwitchTab(obj)
}
}
最后是重写wx.navigateBack方法
function rewriteNavigateBack() {
let oldNavigateBack = wx.navigateBack
wx.navigateBack = function(obj) {
let pages = getCurrentPages()
let leavePath = pages[pages.length - 1].__route__
let enterPath
if (obj.delta) {
enterPath = pages[pages.length - 1 - obj.delta].__route__
} else {
enterPath = pages[pages.length - 2].__route__
}
leavePageLog(leavePath)
obj.success = function(res) {
//进入新页面记录日志
enterPageLog(enterPath)
}
oldNavigateBack(obj)
}
}
结论
本篇只是记录日志,当然也可以在重写的方法wx.navigateTo或wx.switchTab中判断权限,权限不够则不跳转,或跳转到登录完善信息页。
这样大致实现了类似Vue的全局路由,但还是有几个问题
- 点击微信小程序底部的tab不会触发上面任何的方法,也无法监控,需要在tab页的onShow和onHide手动记录日志
- 安卓手机的物理返回键没法监控,不会触发wx.navigateBack方法
那有没有更好的方案呢,答案是有,下一期说