一、官方tabbar
官方文档:https://developers.weixin.qq.com/miniprogram/dev/extended/weui/tabbar.html
1、tabbar配置
- 在app.json里的 tabBar 字段里配置tabbar页面,只有tabbar页面才能显示底部的tabbar。
2、展示层级
- tabbar的展示层级最高,且不占用展示区域,页面展示区域在tabbar之上,比如fixed定位、webview页面等都处在tabbar上面的区域,和tabbar不会相互影响。
3、switchTab
- switchTab 会关闭其他非tabbar页,但tabbar页不会关闭,那么tabbar页的webview类型h5访问地址就不会改变,该tabbar页不会触发onLoad,如需改变需要换用reLaunch。
4、动态修改tabbar
- 修改tabbar的内容使用wx.setTabBarItem(),但是只能修改tabbar上的文字内容、图标,无法修改链接路径。
- 修改tabbar的样式使用wx.setTabBarStyle(),但是只能修改tabbar的背景色、文字颜色、上边框颜色。
- 小程序刚启动时还是会先展示 app.json里配置的默认tabbar,如果动态修改了tabbar,会能看到tabbar改变的过程,手机性能越慢看的越明显,用户体验一般。
- 修改tabbar的相关api只能在tabbar页面才能使用,且reLaunch会重置tabbar数据为app.json的默认配置。
二、自定义tabbar
官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html
1、介绍
- 两种方式:一种采用官方自定义tabbar的方式,但是官方的自定义tabbar实际上也存在不少bug,比如某些情况下真机显示了两层。一种完全自己去实现,其实就是用fixed定位写一个,但是在页面切换的时候会有闪动的问题,因为不同的页面都要引入自定义tabbar这个组件,微信小程序里不同页面的组件并不会完全共用。(猜测官方自定义tabbar和自己自定义的基本方式应该是一样的)
2、配置使用
- 官方自定义tabbar配置方式:在app.json中的tabBar字段里配置custom字段值为true,在代码根目录添加custom-tab-bar组件文件。
- 建议使用 cover-view + cover-image 组件来写tabbar,以保证更高的展示层级。
三、动态设置官方tabbar
- 如上所述,官方tabbar的动态设置有很多局限性,不能动态设置tabbar数量,不能动态设置tabbar项的路径;
- 可以动态设置某个tabbar项的图标文字,如果该项是webview内嵌h5页,那就可以动态设置它的h5地址。
- 但是使用setTabBarItem这个api也有一些坑,一是在非tabbar页无法使用,二是使用wx.reLaunch()会重置tabbar为默认配置,所以需要做一些处理。
以下是处理方式:
1、封装tabbar.js
/**
* tabbar动态设置功能封装
*
* 需要在所有tabbar页的 onShow 方法里调用一下 updateBarItemAll()方法
*/
/**
* tabbar原始配置
* 和app.json保持一致
* icon图片需使用网络地址
*/
const originData = [
{
"pagePath": "pages/index/index",
"iconPath": "https://static.com/tabbar/home.png",
"selectedIconPath": "https://static.com/tabbar/home_selected.png",
"text": "首页"
},
{
"pagePath": "pages/wo/wo",
"iconPath": "https://static..com/tabbar/wo.png",
"selectedIconPath": "https://static.com/tabbar/wo_selected.png",
"text": "我的"
}
]
export default {
originData,
latestData,
// 单例模式获取数据
getTabbarData () {
if (!this.latestData) {
this.latestData = JSON.parse(JSON.stringify(originData))
}
return this.latestData
},
/**
* 动态设置单项tabbar的图标文案
*/
setBarItem ({ index, text, iconPath, selectedIconPath, }) {
const item = { text, iconPath, selectedIconPath, }
// 更新tabbarData单例
const tabbarData = this.getTabbarData()
tabbarData[index].text = item.text
tabbarData[index].iconPath= item.iconPath
tabbarData[index].selectedIconPath= item.selectedIconPath
// 只在当前为tabbar页时才应用修改
const isTabbar = this.isInTabbarPage()
if (isTabbar) {
this.updateBarItem(index, item)
}
},
/**
* 更新所有tabbar项
*/
updateBarItemAll () {
const tabbarData = this.getTabbarData()
tabbarData.forEach((v, i) => {
this.updateBarItem(i, v)
})
},
/**
* 更新单项tabbar
*/
updateBarItem (index, item) {
wx.setTabBarItem({
index: index,
text: item.text,
iconPath: item.iconPath,
selectedIconPath: item.selectedIconPath,
})
},
/**
* 判断是否是tabbar页面
*/
isInTabbarPage (path) {
const tabbarData = this.getTabbarData()
const tabbarRoutes = tabbarData.map(v => v.pagePath)
if (!path) {
const currentPages = getCurrentPages()
const page = currentPages[currentPages.length - 1]
if (!page) {
return true
} else {
path = page.route
}
}
if (path.match(/^\//)) {
path = path.slice(1)
}
const isIn = tabbarRoutes.indexOf(path) > -1
return isIn
},
}
2、使用方式
- 在需要动态修改tabbar的地方不要直接使用官方的wx.setTabBarItem(),而是引用前面封装的tabbar.js,然后调用封装的setBarItem方法。
- 在所有tabbar页的onShow()生命周期里都调用一下封装的updateBarItemAll方法,用于把最新的tabbar数据应用修改上,因为在非tabbar页调用setBarItem时只是修改了实例latestData而没有应用tabbar的数据修改,并且能保证在使用了wx.reLaunch后也能及时应用上最新的tabbar数据。
3、优化建议
-
上述封装的是设置指定某一下标的tabbar项,后续可以考虑对setBarItem做个封装修改,支持通过类型来指定设置某一tabbar,比如指定设置“我的”这一项,这样在tabbar后续调整顺序时就不需要修改index参数。
-
还可以对wx.setTabBarStyle也做个类似的封装,以支持部分样式的动态修改,这里不再赘述了。