vue3 uniapp 自定义底部栏

1,349 阅读1分钟

描述

uniapp vue3 自定义底部导航栏,自动占位,不需要在使用的页面使用margin-bottom或padding-bottom占位。

效果

image.png

tabbar.vue 组件代码

<template>
	<view class="tabbar-area">
		<view class="tabbar-fill" :style="{ height: tabbarHeight }"></view>
		<view class="tabbar-bottom" :style="{ backgroundColor: backgroundColor, height: tabbarHeight }">
			<view class="tabbar-bottom-item" v-for="(item, index) in tabbars" :key="index" @click="switchTab(item)">
				<view class="tabbar-bottom-item-bg">
					<image :src="currentIndex == index + 1 ? item.selectedIconPath : item.iconPath" class="tabbar-bottom-item-icon"></image>
					<view
						class="tabbar-bottom-item-text"
						:style="{
							color: currentIndex == index + 1 ? textActiveColor : textColor
						}"
					>
						{{ item.text }}
					</view>
					<view class="tabbar-bottom-item-count" v-if="item.count">{{ item.count > 99 ? '99+' : item.count }}</view>
				</view>
			</view>
		</view>
	</view>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const props = defineProps({
	currentIndex: {
		type: Number,
		default: 0
	},
	backgroundColor: {
		type: String,
		default: '#fff'
	},
	textColor: {
		type: String,
		default: '#717171'
	},
	textActiveColor: {
		type: String,
		default: '#1ABC9C'
	},
	tabbarHeight: {
		type: String,
		default: '120rpx'
	}
});
const tabbars = ref([
	{
		key: 1,
		text: '首页',
		pagePath: '/pages/comment/index',
		iconPath: '/static/tabbar_comment_unpre.png',
		selectedIconPath: '/static/tabbar_comment_pre.png'
	},
	{
		key: 2,
		text: '消息',
		count: 0,
		pagePath: '/pages/index/index',
		iconPath: '/static/tabbar_message_unpre.png',
		selectedIconPath: '/static/tabbar_message_pre.png'
	},
	{
		key: 3,
		text: '我的',
		pagePath: '/pages/profile/index',
		iconPath: '/static/tabbar_profile_unpre.png',
		selectedIconPath: '/static/tabbar_profile_pre.png'
	}
]);
const switchTab = item => {
	uni.switchTab({
		url: item.pagePath
	});
};
uni.hideTabBar();
</script>

<style lang="scss" scoped>
.tabbar-area {
	padding-bottom: constant(safe-area-inset-bottom);
	padding-bottom: env(safe-area-inset-bottom);
	.tabbar-fill {
		height: 120rpx;
	}
	.tabbar-bottom {
		height: 120rpx;
		width: 100%;
		display: flex;
		box-shadow: 0rpx 4rpx 22rpx 0rpx rgba(0, 0, 0, 0.1);
		z-index: 998;
		box-sizing: border-box;
		position: fixed;
		bottom: 0;
		left: 0;
		.tabbar-bottom-item {
			display: flex;
			align-items: center;
			justify-content: center;
			flex-direction: column;
			flex: 1;

			.tabbar-bottom-item-bg {
				display: flex;
				flex-direction: column;
				align-items: center;
				justify-content: center;
				position: relative;
				.tabbar-bottom-item-icon {
					height: 48rpx;
					width: 48rpx;
					position: relative;
					display: block;
				}

				.tabbar-bottom-item-text {
					display: flex;
					font-size: 20rpx;
					align-items: center;
					justify-content: center;
					margin: 6rpx 0 0 0;
					color: rgb(113, 113, 113);
				}

				.tabbar-bottom-item-count {
					height: 28rpx;
					display: flex;
					background: #ff4d4d;
					border-radius: 1000rpx;
					font-size: 20rpx;
					font-weight: bold;
					color: #ffffff;
					align-items: center;
					justify-content: center;
					padding: 0 4rpx;
					min-width: 20rpx;
					position: absolute;
					top: -8rpx;
					left: 32rpx;
				}
			}
		}
	}
}
</style>

在页面使用

<template>
  <Tabbar :currentIndex="1" />
</template>
<script lang="ts" setup>
import Tabbar from '@/components/BasisLayout/Tabbar.vue';
</script>

在APP.vue

onLaunch: function() {
	        uni.hideTabBar();
}