记录一次事件......
由于业务需求,小程序底部的tabBar需要动态获取并显示,而官方提供的app.json 内tabBar的配置无法再程序中修改,因此需要自定义类似官方效果的tabBar导航栏。
上一篇文章已经描述了如何自定义tabBar以及如何使用(组件来自网络,效果不错,粘贴过来记录学习)。但是,在真机上测试的时候暂时发现了以下两个问题:
- 当前页面可重复点击
- 页面切换与tabBar展示不同步,tabBar会出现“闪现”的情况,视觉效果很糟糕
针对【问题1】:
解决方案:
在tabBar组件上添加事件,点击的时候判断目标页面路由与当前页面路由是否相同,相同则不做跳转处理,否则跳转新页面;
针对【问题2】:
解决方案:
- 用css帧动画过渡,我使用了两种类型的过渡:【tabBar从透明到不透明过渡】,【从各个方向移动到正确tabBar位置过渡】,效果仍然不好,因为无法完美匹配小程序页面切换的动画节奏。
- 既然css搞不定,那就js函数解决吧!
这里主要利用到两个页面跳转函数:【navigateTo】与【navigateBackTo】
因为针对【问题1】的时候已经给组件加了相应的点击事件,具体的跳转等操作逻辑是放在监听的函数里完成的,主要解决思路是利用navigateTo【当前页面入栈,并打开新页面】的特性已经这种方式页面跳转的平滑效果,这样就已经解决了“闪现”问题,但是新的问题是【现在页面栈最多存储10层页面】当大于这个数量后,新的页面无法入栈,也就无法打开新的页面了(mmp!!!)。
因此,就需要使用到【navigateBackTo】。在可以打开新页面的时候(即:当前页面路由不等于目标页面路由),先用 getCurrentPages() 获取当前页面栈(数组),然后遍历页面栈判断目标页面是否存在于其中,如果存在:使用【navigateBackTo】退回到存在的那个页面(同时也是目标页面);否则,使用【navigateTo】打开页面;
以下是具体的实现方法
//tabBar组件里的监听事件
<view class="tabbar_nav" data-url='{{item.pagePath}}' bindtap='__bindNavigate'
</view>
// 调用navTab的一级页面
__bindNavigate: function (e) {
util.switchTabBar(this.route,e);
}
// util.js 中自定义tabBar 跳转具体实现事件
function
switchTabBar
(currRoute,e){
var currUrl = currRoute;
var targeturl = e.currentTarget.dataset.url;
(currUrl.indexOf('/') != 0) && (currUrl = '/' + currUrl);
//当前页面路由不是目标页面路由 进而判断【navigateTo/navigateBack】
if (currUrl != targeturl) {
navigateBackToExistOrNavigateToNew(getCurrentPages(), targeturl)
}
else {
wx.showToast({
title: '试试下拉页面刷新页面吧',
image: "/resources/images/nomore.png"
})
}
}
// 选择具体的跳转方式
function
navigateBackToExistOrNavigateToNew
(routers,targetRouter){
var total = routers.length;
var len = routers.length;
while (len--) {
//如果目标页面存在于页面栈,则navigateBack至页面站内的目标页面
if (('/' + routers[len].__route__) == targetRouter) {
console.log("__route__: /", routers[len].__route__, ' == target:', targetRouter);
console.log("Result:path equal,back delta:", total - 1, ',', len, ',', (total - 1 - len));
wx.navigateBack({
delta: total - 1 - len
})
return true;
} else {
console.log("__route__: /", routers[len].__route__, ' != target:', targetRouter);
}
}
//如果目标页面不存在于页面栈,则navigateTo
wx.navigateTo({
url: targetRouter,
})
return false;
}
当然也是出于无奈,没有找到更好地方法,欢迎更好地解决方案!