微信小程序 自定义 tabBar
最近开发又涉及到了微信小程序,好多年没写过小程序了。
微信小程序一般分为页面、组件,各自有各自的特点,生命周期也不相同
现在要设计一个自定义的 tabBar,本来想写成一个页面,子页面都写成组件,但是这样就会损失页面的许多特性,比如生命周期等等
后面了解了下微信小程序的 tabBar ,发现微信小程序应该分为三种:tab页面、页面、组件
tab页面
是啥?就是底部带 tabBar 的页面,只要按照微信小程序的配置,页面就能自动带上 tabBar,我称之为tab页面
底部的 tabBar 看起来只有一个?错
其实tab页面
底部的 tabBar,就是一个组件,有多少个 tab页面
就有多少个 tabBar!(每个tab页面
可以通过wx.getTabBar()
访问自己的 tabBar 实例)
按照微信小程序你可以弄个简单的tabBar,但是它是固定的,设置有多少个,底部就显示多少个,数量也有限制。但是可以自己做个自己的tabBar(微信小程序官网)
搜索了一些其他人的实现,感觉有点啰嗦,设计的也不完美
这里整合一下我写的,步骤也简单,两个步骤:
步骤一
按照原始的tabBar 配置,修改文件:/app.json
page 这里必须写上
tabBar.custom
为true,这个表面是自定义的 tabBar
tabBar.list
把所有的 tab页面
都列在这,自定义的只需要pagePath 注意前面没''。
系统会根据以上配置进行解析处理,这样就可以通过 wx.switchTab
跳转到 tab页面
了, page就会自动带上自定义tabBar
{
"pages": [
"pages/index1/index1",
"pages/index2/index2",
"pages/index3/index3",
"pages/index4/index4"
],
"tabBar": {
"custom": true,
"list": [
{
"pagePath": "pages/index1/index1"
},
{
"pagePath": "pages/index2/index2"
},
{
"pagePath": "pages/index3/index3"
},
{
"pagePath": "pages/index4/index4"
}
]
}
}
步骤二
和 pages 文件夹并列,建立文件夹custom-tab-bar
,里面命名为 index的组件,里面我还额外建立了一个文件customTabBar.ts
(使用 js 用 js 命名就可以了),以下是各个文件的代码:
代码
customTabBar.ts
// tabBar的data
export const tabBarData: {
listIndex: number,// 底部高亮下标
color: string,
selectedColor: string,
backgroundColor: string,
list: Array<{
pagePath: string,
iconPath: string,
selectedIconPath: string,
text: string,
}>
} = {
listIndex: 0,
color: "#5F5F5F",
selectedColor: "#07c160",
backgroundColor: "#F7F7F7",
list: []
}
// 微信的setData貌似不会对原有的对象进行处理,直接引用上面的tabBarData
// 我舍弃了下面这个方法,毕竟会有一丢丢的性能损失?
// export const getTabBarData = () => JSON.parse(JSON.stringify(tabBarData));
// 所有的list,和 app.json 保持一致
const list = [
{
"pagePath": "pages/index1/index1",
"iconPath": "/assets/首页.png",
"selectedIconPath": "/assets/首页-active.png",
"text": "按钮1"
},
{
"pagePath": "pages/index2/index2",
"iconPath": "/assets/首页.png",
"selectedIconPath": "/assets/首页-active.png",
"text": "按钮2"
},
{
"pagePath": "pages/index3/index3",
"iconPath": "/assets/首页.png",
"selectedIconPath": "/assets/首页-active.png",
"text": "按钮3"
},
{
"pagePath": "pages/index4/index4",
"iconPath": "/assets/首页.png",
"selectedIconPath": "/assets/首页-active.png",
"text": "按钮4"
}
]
// 根据角色设置合适的 list,并更新 tabBarData
// 注意每个 tab 页面,都有自己的独立的 tabbar 组件
// 注意每次设置后都要 wx.relaunch,清空页面缓存
export const setCustomTabBarByRole = (role: 'member' | 'tourist', defaultIndex = 0) => {
tabBarData.listIndex = defaultIndex;
if (role === 'member') {
tabBarData.list = list.slice();
} else if (role === 'tourist') {
tabBarData.list = list.slice(0,3);
}
}
export const changeCustomTabBarIndex = (index: number) => {
const targetNav = tabBarData.list[index];
if (targetNav) {
tabBarData.listIndex = index;
const { pagePath } = targetNav;
wx.switchTab({
// 注意这里路径要加上 '/',而 app.json 不能加上 '/',会报错!
url: '/' + pagePath
})
}
}
index.less
/* custom-tab-bar/index.wxss */
.tabBar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 48px;
background: white;
display: flex;
padding-bottom: env(safe-area-inset-bottom);
border-top: 1px solid #c1c1c1;
}
.tabBarItem {
flex: 1;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.itemImage {
width: 26px;
height: 26px;
}
.itemTitle {
font-size: 10px;
}
index.ts
// custom-tab-bar/index.ts
import { tabBarData, changeCustomTabBarIndex } from "./customTabBar";
Component({
attached() {
// 经过实验,微信小程序页面、组件,data只支持字面量初始化,不支持函数初始化
// 所以在这个时机进行初始化data!
// 注意 setData函数 不会对参数造成影响,所以这里直接放入tabBarData
// 而不是通过 JSON.parse(JSON.stringify(obj)) 复制一份
this.setData(tabBarData);
},
methods: {
switchTab(event: any) {
const { index } = event.currentTarget.dataset;
changeCustomTabBarIndex(index);
},
}
})
index.wxml
<!--custom-tab-bar/index.wxml-->
<view class="tabBar">
<view class="tabBarItem" wx:for="{{list}}" wx:key="index" data-index="{{index}}" bindtap="switchTab">
<image class="itemImage" src="{{listIndex === index ? item.selectedIconPath : item.iconPath}}"></image>
<view class="itemTitle" style="color: {{listIndex === index ? selectedColor : color}}">{{item.text}}</view>
</view>
</view>
效果
注意设置设置底部菜单的时候,要 wx.relaunch()
,这样才可以清除缓存的影响,因为 tab 页面
是会缓存的
其他
可以不清除缓存,直接设置吗?可以
但我没实现(因为不需要),我这里实际上每个 tabBar 实例,只设置了一次data,后续就没管了
而且,tabBar 实例应该和页面路径相匹配,我这里匹配不了,因为只有页面才有资格获取路径
如何实现呢?讲讲方式,因为每个 tabBar 实例,并不能够获取当前页面路径。只有页面才能够获取
所以设置 tabBar 实例的时候,可以通过页面来设置,前面讲到只要是 tab页面
,tab页面
可以通过wx.getTabBar()
获取属于它的 tabBar 实例
每次点击这个页面的时候(也就是 onShow 的时候),就动态设置tabBar的值,参考这个同学
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了