封装原因
uniapp提供的tabbar样式无法满足产品需求
注意事项
- 使用自定义底部导航组件,需要在使用的页面中使用以下代码:uni.hideTabBar();
- 在pages.json文件中的tabBar对象可以简化配置,如下图
封装代码
<template>
<view
class="tabbar-box"
:style="{ 'padding-bottom': safeAreaBottomHeight + 'px', 'z-index': zIndex }"
>
<view
class="tabbar-box-item"
v-for="(item, index) in tabbarList"
@click="goPage(item)"
:key="index"
>
<image :src="props.type === item.type ? item.activeUrl : item.url"></image>
<text :class="{ active: props.type === item.type }">{{ item.title }}</text>
</view>
</view>
<!-- 占位 -->
<view :style="{ height: tabbarHeight + 'px' }"></view>
</template>
<script setup>
import { ref, onMounted, getCurrentInstance, nextTick } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const { proxy } = getCurrentInstance();
const props = defineProps({
type: {
type: String,
default: 'home',
},
zIndex: {
type: Number,
default: 1000,
},
});
const emit = defineEmits(['getTabbarHeight']);
let tabbarHeight = ref('');
onMounted(() => {
getSafeAreaBottomHeight();
getTabbarHeight();
});
const safeAreaBottomHeight = ref(0);
// 获取安全区域底部高度
function getSafeAreaBottomHeight() {
const deviceInfo = uni.getDeviceInfo();
const windowInfo = uni.getWindowInfo();
if (deviceInfo.osName == 'ios') {
safeAreaBottomHeight.value = windowInfo.safeAreaInsets.bottom;
} else {
safeAreaBottomHeight.value = windowInfo.safeAreaInsets.bottom
? windowInfo.safeAreaInsets.bottom
: 20;
}
}
// 获取 tabbar-box 的高度
async function getTabbarHeight() {
await nextTick();
let query = uni.createSelectorQuery().in(proxy);
query
.select('.tabbar-box')
.boundingClientRect((data) => {
tabbarHeight.value = data.height;
emit('getTabbarHeight', tabbarHeight.value);
})
.exec();
}
let tabbarList = ref([
{
title: '首页',
type: 'home',
path: '/pages/home/index',
url: '/static/images/tabbar/home-not-active.png',
activeUrl: '/static/images/tabbar/home-active.png',
},
{
title: '我的',
type: 'user',
path: '/pages/user/index',
url: '/static/images/tabbar/user-not-active.png',
activeUrl: '/static/images/tabbar/user-active.png',
},
]);
function goPage(item) {
if (item.type == props.type) return;
uni.switchTab({
url: item.path,
});
}
</script>
<style lang="scss" scoped>
.tabbar-box {
width: 100%;
position: fixed;
bottom: 0;
left: 0;
padding: 40rpx 20rpx;
background: #fff;
box-shadow: 0rpx -1rpx 21rpx 0rpx rgba(131, 128, 127, 0.1);
border-radius: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
.tabbar-box-item {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
image {
width: 40rpx;
height: 40rpx;
margin-bottom: 10rpx;
}
text {
font-size: 22rpx;
font-weight: 500;
color: #999999;
}
.active {
color: #2d99a1;
}
}
}
</style>
页面使用
<myTabbar type="home" @getTabbarHeight=getTabbarHeight></myTabbar>
onMounted(() => {
uni.hideTabBar();
});
function getTabbarHeight(height){
console.log('tabbarHeight', height);
}
问题解释
Q:为什么使用了自定义tabbar组件还需要保留uniapp提供的tabbar、为什么要在使用组件的页面隐藏tabbar?
A:一开始封装的时候也没有保留原生的tabbar,然后组件中页面跳转的方式使用的就是reLaunch而不是switchTab,但是使用过程中发现每次进行tabbar切换的时候都会导致页面有很明显的切换感觉,和原生的tabbar切换效果相比不够丝滑
Q:其他的跳转方式无法满足吗?
A:其他跳转方式都无法满足要求,navigateTo会增加页面栈、redirectTo和reLaunch一样会导致页面有很明显的切换感觉,所以最后只能使用switchTab方式进行跳转