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()
}
async created() {
//请求数据
await this.getAppNav();
},
methods:{
getAppNav(){
···请求内容
arr 为请求数据
uni.setStorageSync('tabber', arr)
}
}
写一个tabber组件
需求:动态配置底部tabber。
根据后台配置展示图文/图标/文字的底部tabber的类型
地址,跳转路径,图片都可以配置
<template>
<view v-if="show" 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>
const http = require('@/utils/http.js')
const config = require('@/utils/config.js')
export default {
data() {
return {
// 当前选中的tabbar菜单索引
currentIndex: 0,
list: [],
type: 1,
paddingBottomHeight: 0,
show:true,
}
},
created() {
let that = this;
uni.getSystemInfo({
success: function(res) {
let model = ['X', 'XR', 'XS', '11', '12', '13', '14', '15'];
model.forEach(item => {
//适配iphoneX以上的底部,给tabbar一定高度的padding-bottom
if (res.model.indexOf(item) != -1 && res.model.indexOf('iPhone') != -1) {
that.paddingBottomHeight = 40;
}
})
}
});
let selectedIndex = uni.getStorageSync('selectedIndex')
that.currentIndex = selectedIndex || 0
const list = uni.getStorageSync('tabber')
if (!!list) {
that.list = list
} else {
that.getAppNav()
}
},
methods: {
getAppNav() {
http.request({
url: `/appNav/list`,
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) => {
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购物车 2个人中心 4自定义路径 5微页面
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
// 获取当前页面实例对象
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
// 获取当前页面路径
const currentPath = currentPage.route; // 或者使用 currentPage.$page.fullPath 获取全路径
const item = arr.filter((v) => currentPath == v.path)
console.log(item,'itme')
this.show = item.length>0 ? true:false,
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>
在tabber组件里判断是否获取tabber数据,没有就获取有就再次请求,因为在操作中,我发现第一次拿不到app.vue缓存的数据,判断没有数据就再次请求一次。苹果还需要设置底部距离。
注册
在main.js
文件中引入tabber组件
import tabBar from './components/tabber'
Vue.component('tab-bar', tabBar)
使用
在需要用的页面直接引入即可
//index页面
<template>
<view>
<view>首页</view>
<tab-bar></tab-bar>
</view>
</template>
注:uni.switchTab 方法只能用于跳转 TabBar 页面,无法跳转非 TabBar 页面