赞
踩
自定义tabBar的性能体验会低于原生tabBar,小程序端非必要不要自定义。但原生tabBar是相对固定的配置方式,可能无法满足所有场景,这就涉及到自定义tabBar。
在 pages.json
中的 tabBar
项指定 custom
字段,同时其余 tabBar
相关配置也补充完整
"tabBar": {
"color": "#ffffff",
"selectedColor": "#6777FD",
"custom": true,
"list": [{},{},{}]
}
①自定义公共组件
在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 配置页面仍然是必需的,为什么?
这两者的作用不同:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。