uniapp自定义Tabbar
效果图
- tip: 如效果图tabbar切换时感觉会小闪 ,个人在真机上测试不明显
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/0dec9e648c6bd1fbfa0452d333ca3b08.gif)
定义组件
template
<template>
<view v-if="tabbarList">
<view class="tabbar" :style="{ backgroundColor: bottomNav.backgroundColor }">
<view class="tabbar_content">
<view class="tabbar-border"></view>
<view class="tabbar_item" :class="{ bulge: isBulge && index == 2 }" v-for="(item, index) in tabbarList" :key="index" @click="redirectTo(item.link)">
<view class="tabbar_btn">
<view class="icon">
<image class="whFull" :src="verify(item.link) ? $util.img(item.selectedIconPath) : $util.img(item.iconPath)" />
</view>
<view class="label":style="{ color: verify(item.link) ? bottomNav.textHoverColor : bottomNav.textColor }">{{ item.text }}</view>
</view>
</view>
</view>
</view>
</view>
</template>
js
<script>
export default {
name: 'diy-bottom-nav',
props: {
value: {
type: Object
},
type: {
type: String,
default: ''
},
siteId: {
type: [Number, String],
default: 0
}
},
data() {
return {
jumpFlag: true,
special: ['/member/signIn/index/index'],
bottomNav: {
bulge: true,
textHoverColor: '#1B1B1B',
textColor: '#999999',
backgroundColor: '#ffffff',
},
tabbarList: [
{
iconPath: "upload/xxx/home.png",
selectedIconPath: "upload/xxx/home_selected.png",
text: "首页",
link: {
type: 1,
wap_url: "/xxx"
},
},
{
iconPath: "upload/xxx/order.png",
selectedIconPath: "upload/xxx/order_selected.png",
text: "订单",
link: {
type: 1,
wap_url: "/xxx"
}
},
{
iconPath: "upload/xxx/user.png",
selectedIconPath: "upload/xxx/user_selected.png",
text: "发布",
link: {
type: 1,
wap_url: "/xxx"
}
},
{
iconPath: "upload/xxx/notice.png",
selectedIconPath: "upload/xxx/notice_selected.png",
text: "消息",
link: {
type: 1,
wap_url: "/xxx"
}
},
{
iconPath: "upload/xxx/user.png",
selectedIconPath: "upload/xxx/user_selected.png",
text: "我的",
link: {
type: 1,
wap_url: "/xxx"
}
}
],
};
},
mounted() {
let currentPage = getCurrentPages()[getCurrentPages().length - 1];
this.currentRoute = currentPage.route;
},
computed: {
isBulge() {
if (this.tabbarList) {
return this.tabbarList.length == 5 && this.special.indexOf(this.currentRoute) == -1 && this.bottomNav.bulge;
} else {
return false;
}
}
},
methods: {
redirectTo(link) {
this.$emit('callback');
if (!this.jumpFlag) return;
this.jumpFlag = false;
setTimeout(() => {
this.jumpFlag = true;
}, 300);
if (link == null || link == '' || !link.wap_url) return false;
if (link.wap_url.indexOf(this.currentRoute) != -1) return false;
let jump = true;
let arr = getCurrentPages().reverse();
for (let i = 0; i < arr.length; i++) {
if (link.wap_url.indexOf(arr[i].route) != -1) {
jump = false;
uni.navigateBack({
delta: i
});
break;
}
}
if (jump) {
uni.navigateTo({
url: link.wap_url
})
}
},
verify(link) {
if (link == null || link == '' || !link.wap_url) return false;
if (link.wap_url.indexOf(this.currentRoute) != -1) {
return true;
}
return false;
},
getBottomNav() {
let url = '/api/view/bottomNav';
let data = {};
if (this.siteId) {
url = '/api/view/shopBottomNav';
data.site_id = this.siteId;
}
this.$api.sendRequest({
url: url,
data: data,
success: res => {
let data = res.data;
if (data && data.value && data.value.length) {
let value = JSON.parse(data.value);
this.bottomNav = value;
this.tabbarList = value.list;
this.$store.commit('setTabbarList', JSON.parse(data.value));
this.$forceUpdate();
}
}
});
}
}
};
</script>
tabbar接口返回数据效果图
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/0682432319685829f49fac0164aaacdb.png)
css
<style lang="scss" scoped>
.whFull {
width: 100%;
height: 100%;
}
.tabbar {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
z-index: 998;
box-sizing: border-box;
padding-bottom: env(safe-area-inset-bottom);
.tabbar_content {
display: flex;
height: 50px;
padding: 5px 0;
}
.tabbar-border {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
transform: scaleY(0.5);
background-color: rgba(228,231,237, 0.9);
}
.tabbar_item {
display: flex;
align-items: center;
flex: 1;
flex-direction: column;
box-sizing: border-box;
height: 100%;
.tabbar_btn {
position: relative;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
.icon {
position: relative;
display: inline-block;
width: 40rpx;
height: 40rpx;
}
.label {
position: relative;
text-align: center;
font-size: 12px;
line-height: 1;
margin-top: 12rpx;
}
}
.bulge {
.icon {
margin-top: -30px;
border-radius: 50%;
width: 50px;
height: 50px;
padding: 2px;
border-top: 1px solid #e4e7ed;
background-color: #fff;
box-sizing: border-box;
}
}
}
</style>
使用组件
- 这里简单使用,把获取
tabbar
接口放在子组件,判断是否存在siteId
请求对应接口。
<template>
<view>
<bottom-nav></bottom-nav>
<!-- or -->
<bottom-nav :siteId="siteId"></bottom-nav>
</view>
</template>
<script>
import bottomNav from '@/components/bottom-nav/index.vue'
export default {
components: {
bottomNav
},
}
</script>