uniapp自定义tabber
注:因为项目是老代码,我不想改动太大,所以用的自定义这种自定义tabber方法,会出现点击的时候图标闪烁问题,如果想要更好的解决建议把tabBar和页面组件都放在单页中用v-if判断,进行切换,单页切换的缺点是不能进行路由跳转
效果
pc端:
小程序端
解析
小程序底部tabber是可以动态配置的,看了下方法可以改,页面写好了,准备处理小程序的时候发现,uniapp 本身的动态设置tabbar方法 uni.setTabBarItem(OBJECT),好像没办法修改个数和修改跳转路径。
uni.setTabBarItem(OBJECT)
uni.setTabBarItem是uni-app框架中用于动态设置原生底部tabbar组件中的某一项的方法
uni.setTabBarItem({
index: Number,
text: String,
iconPath: String,
selectedIconPath: String
});
index
:Number类型,必选项,表示要修改的tab的下标,从0开始编号。text
:String类型,可选项,表示要修改的tab的文本内容。iconPath
:String类型,可选项,表示要修改的tab的图片路径,路径格式和大小限制参考uni-app官方文档。selectedIconPath
:String类型,可选项,表示要修改的tab被选中时的图片路径,路径格式和大小限制参考uni-app官方文档
问题:
1.修改pagePath不跳转。
用这个方法改完后,发现点击时取的是pages.json
的tabBar
下list
的数据。
2.无法修改tabber个数。
UniApp 中的 uni.setTabBarItem
方法用于设置修改底部 TabBar 菜单栏的图标、文字等属性,但是该方法并不能直接用于修改 TabBar 的个数。修改 pages.json
文件中的 tabBar.list
属性,添加或删除需要的 TabBar 项,即可实现修改 TabBar 的个数。(在修改 pages.json
文件中的 tabBar.list
属性之后,可能需要重新编译小程序才能生效)
3.动态配置底部tabber三种展示方式。图文/图标/文字。
设置图标为空后,图标位置空白,样式没有修改,只展示了文字。
自定义tabber
在App.vue页面中
//隐藏tabber
onLaunch: function(options) {
uni.hideTabBar()
}
写一个tabber组件
需求:动态配置底部tabber。
根据后台配置展示图文/图标/文字的底部tabber的类型
地址,跳转路径,图片都可以配置
<template>
<view class="tabbar-container">
<view
:class="currentIndex === item.index ? 'tabbar-item is-active' : 'tabbar-item'"
v-for="(item, index) in list"
:key="index"
@click="switchTab(item)"
>
<image
v-if="type != 3"
class="tabbar-icon"
:src="currentIndex === item.index ? item.selectedIconPath : item.iconPath"
/>
<view v-if="type != 2" :class="currentIndex === item.index ? 'tabbar-text is-active' : 'tabbar-text'">{{
item.text
}}</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
// 当前选中的tabbar菜单索引
currentIndex: 0,
list: [],
type: 1,
}
},
created() {
let selectedIndex = uni.getStorageSync('selectedIndex')
this.currentIndex = selectedIndex || 0
const list = uni.getStorageSync('tabber')
if (!!list) {
this.list = list
} else {
this.getAppNav()
}
},
methods: {
getAppNav() {
http.request({
url: `接口名`,
method: 'GET',
callBack: (res) => {
let arr = []
if (res.length) {
this.type = res[0].type
const shopId = uni.getStorageSync('shopId')
uni.setStorageSync('appNavList', res)
let picDomain = config.picDomain
res.forEach((v, i) => {
//图片是传的字符串拼接的2个string
let img = v.pic.split(',')
let item
let text = v.type !== 2 ? v.title : ''
let index = i
let pagePath = v.path
let path = v.path
// linkType // 1.首页 2.购物车 3.个人中心 4.B2C商城 5微页面 6分类
//type 1图文 2图标 3 文字
if (v.linkType == 5) {
path = 'pages/feature-index/feature-index0'
pagePath = `pages/feature-index/feature-index0?renovationId=${v.path}&shopId=${shopId}`
}
let obj = {
path,
linkType: v.linkType,
pagePath,
index,
}
if (v.type == 2) {
item = {
...obj,
iconPath: picDomain + img[0],
selectedIconPath: picDomain + img[1],
text,
}
} else if (v.type == 1) {
item = {
...obj,
text,
iconPath: picDomain + img[0],
selectedIconPath: picDomain + img[1],
}
} else {
item = {
...obj,
text,
iconPath: '',
selectedIconPath: '',
}
}
arr.push(item)
})
this.list = arr
uni.setStorageSync('tabber', arr)
}
},
})
},
/**
* @description: 切换
* @param {*} item
*/
switchTab(item) {
let url = '/' + item.pagePath
// uni.switchTab 方法只能用于跳转 TabBar 页面,无法跳转非 TabBar 页面
if (item.linkType == 5) {
uni.reLaunch({ url })
} else {
uni.switchTab({ url })
}
// uni.navigateTo({url})
this.list.forEach((v) => {
if (item.pagePath === v.pagePath) {
uni.setStorageSync('selectedIndex', item.index)
}
})
},
},
}
</script>
<style lang="css" scoped>
.tabbar-container {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 50px;
background: #fff;
border-top: 1px solid #dedede;
display: flex;
justify-content: space-around;
z-index: 9999;
}
.tabbar-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
padding-top: 3px;
color: #999;
}
.tabbar-text {
font-size: 12px;
margin-top: 2px;
color: #333;
}
.tabbar-icon {
width: 24px;
height: 24px;
}
/* .tabbar-text {
color: #07c160;
} */
.is-active {
color: #07c160;
}
</style>
注册
在main.js
文件中引入tabber组件
import tabBar from './components/tabber'
Vue.component('tab-bar', tabBar)
使用
在需要用的页面直接引入即可
//index页面
<template>
<view>
<view>首页</view>
<tab-bar></tab-bar>
</view>
</template>
判断
在后台配置的时候其实就已经限制了tabber的路径,所以只需要在固定页面引入即可,但是有可能该页面没有配置,所以我们再增加一个判断
function isTabber(){
const tabber = uni.getStorageSync('tabber');
if(tabber){
// 获取当前页面实例对象
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
// 获取当前页面路径
const currentPath = currentPage.route; // 或者使用 currentPage.$page.fullPath 获取全路径
const item = tabber.filter((v) => currentPath == v.path)
return item.length>0 ? true:false
}
return false
}
因为页面是后台配置的,所以我们能拿到url对比,如果判断有则展示,在页面中修改
onLoad: function (options) {
this.showTabber = util.isTabber()
},
<tab-bar v-if='showTabber'></tab-bar>
增加一个showTabber判断是否展示tabber,在可能展示的页面中的onLoad中调用方法判断是否展示
注:uni.switchTab 方法只能用于跳转 TabBar 页面,无法跳转非 TabBar 页面