阅读量:2
自定义tabBar的性能体验会低于原生tabBar,小程序端非必要不要自定义。但原生tabBar是相对固定的配置方式,可能无法满足所有场景,这就涉及到自定义tabBar。
一、使用流程
1、配置信息
在 pages.json
中的 tabBar
项指定 custom
字段,同时其余 tabBar
相关配置也补充完整
"tabBar": { "color": "#ffffff", "selectedColor": "#6777FD", "custom": true, "list": [{},{},{}] }
2、添加tabBar代码文件
①自定义公共组件
在components
目录下新建组件页面CustomTabBar
,在CustomTabBar.vue
中开发自定义组件
<template> <view class="tabBar"></view> </template> <script> export default { props: { selected: Number }, data() { return { color: "#fff", selectedColor: "#6777FD", list: [{},{},{}] } }, methods: { switchTab(url) { uni.switchTab({ url }) } } } </script> <style lang="scss"> </style>
在需要用到tabBar
的页面引入注册并使用组件,通过父子组件通信
的方式传参当前是哪个索引页面selected
,在子组件通过props
接收并使用
<script> import CustomTabBar from "@/components/CustomTabBar/CustomTabBar.vue" export default { components: { CustomTabBar } } </script> <template> <view> <custom-tab-bar :selected="1" /> </view> </template>
②自定义tabbar
在根目录
创建custom-tab-bar
文件夹,里面创建index.js、index.json、index.wxml、index.wxss
文件进行开发,而不是vue
文件,uniapp编译器会直接拷贝
该目录到微信小程序中。
在index.js
中:
Component({ /** * 组件的属性列表 */ properties: { }, /** * 组件的初始数据 */ data: { selected: 0, color: "#fff", selectedColor: "#6777FD", list: [{},{},{}] }, /** * 组件的方法列表 */ methods: { switchTab(e) { const data = e.currentTarget.dataset const url = data.path wx.switchTab({ url }) }, } })
注意:如需实现 tab 选中态,要在当前页面下,通过 getTabBar 接口获取组件实例,并调用 setData 更新选中态
onShow() { // 原生微信小程序 if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 0 }) } // vue2 if (typeof this.$mp.page.getTabBar === 'function' && this.$mp.page.getTabBar()) { this.$mp.page.getTabBar().setData({ selected: 0 }) } // vue3 if (typeof this.scope.page.getTabBar === 'function' && this.scope.page.getTabBar()) { this.scope.page.getTabBar().setData({ selected: 0 }) } }
二、具体案例
在pages.json
中:
"tabBar": { "color": "#ffffff", "selectedColor": "#6777FD", "custom": true, "list": [{ "pagePath": "pages/aboutFind/use/use", "iconPath": "static/image/icon_find2.png", "selectedIconPath": "static/image/icon_find1.png", "text": "使用" }, { "pagePath": "pages/index/index", "iconPath": "static/image/icon_go2.png", "selectedIconPath": "static/image/icon_go1.png", "text": "通行" }, { "pagePath": "pages/myInfo/myInfo", "iconPath": "static/image/icon_set2.png", "selectedIconPath": "static/image/icon_set1.png", "text": "我的" } ] }
①自定义公共组件
在CustomTabBar.vue
中:
<template> <view class="tabBar"> <view class="cont"> <block v-for="(item,index) in list" :key="index" class="cont-item"> <view @click="switchTab(item.pagePath)" :class="{'search': item.search ? true : false, 'item': !item.search, 'on': selected === index ? true : false, 'off': selected != index ? true : false}"> <image :src=" selected===index ? item.selectedIconPath : item.iconPath"> </image> <view :class="{'txt': true,'selectedColor': selected === index ? true : false}">{{item.text}}</view> </view> </block> </view> </view> </template> <script> export default { props: { selected: Number }, data() { return { color: "#fff", selectedColor: "#6777FD", list: [{ pagePath: "/pages/aboutFind/use/use", text: "使用", iconPath: "/static/image/icon_find2.png", selectedIconPath: "/static/image/icon_find1.png" }, { pagePath: "/pages/index/index", text: "通行", iconPath: "/static/image/icon_go2.png", selectedIconPath: "/static/image/icon_go1.png", search: true }, { pagePath: "/pages/myInfo/myInfo", text: "我的", iconPath: "/static/image/icon_set2.png", selectedIconPath: "/static/image/icon_set1.png" } ] } }, methods: { switchTab(url) { uni.switchTab({ url }) } } } </script> <style lang="scss"> .tabBar { z-index: 100; width: 100%; position: fixed; bottom: 0; font-size: 28rpx; background-color: #fff; color: #636363; border-radius: 50rpx 50rpx 0px 0px; } .cont { z-index: 0; height: calc(100rpx + env(safe-area-inset-bottom) / 2); padding-bottom: 30rpx; display: flex; justify-content: space-around; .item { font-size: 24rpx; position: relative; width: 15%; text-align: center; padding: 0; display: block; height: auto; line-height: 1; margin: 0; background-color: inherit; overflow: initial; justify-content: center; align-items: center; padding-top: 20rpx; } .item:first-child { right: 45rpx; } .item:last-child { left: 45rpx; } .item image:first-child { width: 43rpx !important; height: 43rpx !important; margin: auto } .item image:last-child { width: 41rpx !important; height: 43rpx !important; margin: auto } .txt { margin-top: 20rpx; } .on { position: relative; } .on:not(:nth-child(2)):before { content: ""; display: block; position: absolute; top: 0; width: 100%; height: 6rpx; background-color: #00BCD4; border-radius: 120rpx !important; } .search { position: absolute; left: 50%; transform: translate(-50%, 0); top: -50rpx; display: flex; flex-direction: column; justify-content: center; align-items: center; } .search image { width: 100rpx !important; height: 100rpx !important; z-index: 2; border-radius: 100%; } .search .txt { margin-top: 26rpx; } .selectedColor { color: #00BCD4; } } </style>
在使用到CustomTabBar.vue
组件的三个页面中,如index首页
:
<script> import CustomTabBar from "@/components/CustomTabBar/CustomTabBar.vue" export default { components: { CustomTabBar } } </script> <template> <view> <!-- 传对应页面在list数组中位置的索引值 --> <custom-tab-bar :selected="1" /> </view> </template>
②自定义tabbar
在index.js
中:
Component({ /** * 组件的属性列表 */ properties: { }, /** * 组件的初始数据 */ data: { selected: 0, color: "#fff", selectedColor: "#6777FD", list: [ { pagePath: "/pages/aboutFind/use/use", text: "使用", iconPath: "/static/image/icon_find2.png", selectedIconPath: "/static/image/icon_find1.png" }, { pagePath: "/pages/index/index", text: "通行", iconPath: "/static/image/icon_go2.png", selectedIconPath: "/static/image/icon_go1.png", search: true }, { pagePath: "/pages/myInfo/myInfo", text: "我的", iconPath: "/static/image/icon_set2.png", selectedIconPath: "/static/image/icon_set1.png" } ] }, /** * 组件的方法列表 */ methods: { switchTab(e) { const data = e.currentTarget.dataset const url = data.path wx.switchTab({ url }) }, } })
在index.json
中:
{ "component": true, "usingComponents": {} }
在index.wxml
中:
<view class="tabBar"> <view class="cont"> <block wx:for="{{list}}" wx:key="index" class="cont-item"> <view data-path="{{item.pagePath}}" data-index="{{item.pagePath}}" bindtap="switchTab" class="{{item.search?'search':'item'}} {{selected === index ? 'on' : 'off'}}"> <image src="{{selected === index ? item.selectedIconPath : item.iconPath}}"></image> <view class="txt {{selected === index ? 'selectedColor' : ''}}">{{item.text}}</view> </view> </block> </view> </view>
在index.wxss
中:
.tabBar { z-index: 100; width: 100%; position: fixed; bottom: 0; font-size: 28rpx; background-color: #fff; color: #636363; border-radius: 50rpx 50rpx 0px 0px; } .cont { z-index: 0; height: calc(100rpx + env(safe-area-inset-bottom) / 2); padding-bottom: 30rpx; display: flex; justify-content: space-around; } .cont .item { font-size: 24rpx; position: relative; /* flex: 1; */ width: 15%; text-align: center; padding: 0; display: block; height: auto; line-height: 1; margin: 0; background-color: inherit; overflow: initial; justify-content: center; align-items: center; padding-top: 20rpx; } .cont .item:first-child { right: 45rpx; } .cont .item:last-child { left: 45rpx; } .cont .item image:first-child { width: 43rpx !important; height: 43rpx !important; margin: auto } .cont .item image:last-child { width: 41rpx !important; height: 43rpx !important; margin: auto } .cont .txt { margin-top: 20rpx; } .cont .on { position: relative; } .cont .on:not(:nth-child(2)):before { content: ""; display: block; position: absolute; top: 0; width: 100%; height: 6rpx; background-color: #00BCD4; border-radius:120rpx !important; } .cont .search { position: absolute; left: 50%; transform: translate(-50%,0); top: -50rpx; display: flex; flex-direction: column; justify-content: center; align-items: center; } .cont .search image { width: 100rpx !important; height: 100rpx !important; z-index: 2; border-radius: 100%; } .cont .search .txt { margin-top: 26rpx; } .cont .selectedColor { color: #00BCD4; }
在使用到custom-tab-bar
的三个页面中:
onShow() { if (typeof this.$mp.page.getTabBar === 'function' && this.$mp.page.getTabBar()) { this.$mp.page.getTabBar().setData({ selected: 1 }) } }
三、疑惑
尽管在自定义页面中已经写了页面的配置项,但在 app.json 中的 list 配置页面仍然是必需的,为什么?
这两者的作用不同:
- 自定义页面配置项:这些配置项是针对你自定义的页面的,包括页面路径、页面标题、页面使用的窗口配置等。这些配置项用于描述单个页面的属性和行为。
- app.json 中的 list 配置页面:这些配置项用于描述 TabBar 中的各个页面,包括页面路径、页面标题、页面图标路径等。这些配置项告诉微信客户端哪些页面需要在 TabBar 中显示,并且控制它们在 TabBar 中的位置和样式。