更新记录

1.0.6(2025-09-03) 下载此版本

更新完整组件使用示例

1.0.5(2025-09-03) 下载此版本

补充信息

1.0.4(2025-09-03) 下载此版本

重新修改框架

查看更多

平台兼容性

uni-app(4.07)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟

uni-app x(4.07)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - - -

xz-tabBar 自定义tabBar

实现隔离底部安全区域和通过插槽自定义凸起的tabBar

Props

属性名 类型 是否必填 默认 可选 说明
list Array true [] tabBar数据;格式:[{text:'名称',pageKey:'路由key',pagePath:'路由地址',iconPath:'默认icon',selectedIconPath:'选中icon'}];pageKey必须唯一
pageKey String true "" 当前tabBar唯一值
safeAreaShowType String true padding padding(内边距)、margin(外边距) 安全区域类型
tabBarTopType String false border border(边框)、shadow(阴影) tabBar上边框显示类型
color String false #333333 文字颜色
selectColor String false #ff0000 选中文字颜色
tabBarStyle Object false {} tabBa自定义样式;格式{height: '100rpx'}
tabBarItemStyle Object false {} tabBa每一项自定义样式;格式{height: '100rpx'}

Emits

事件名 接收值 说明
openPage url 接收点击tabBar项的路由地址
getTabHeight height 接收tabBar元素的高度

Slots

插槽 说明
protrusion 中间凸起,请查看代码示例中凸起样式

代码示例

常规数据

const list = [
    {
        text: '首页',
        pageKey: 'index',
        pagePath: '/pages/index/index',
        iconPath: '/static/home.png',
        selectedIconPath: '/static/selectedHome.png'
    },
    {
        text: '我的',
        pageKey: 'user',
        pagePath: '/pages/user/index',
        iconPath: '/static/user.png',
        selectedIconPath: '/static/selectedUser.png'
    }
];

const openPage = (url) => {
    uni.switchTab({
        url
    });
};

普通样式

<template>
    <xz-tabBar :list="list" pageKey="index" selectColor="#1296db" @openPage="openPage"></xz-tabBar>
</template>

凸起样式

<template>
    <xz-tabBar tabBarTopType="shadow" :list="list" pageKey="index" selectColor="#1296db" @openPage="openPage">
        <template #protrusion>
            <view class="protrusion" @click="openPage('/pages/menu/index')">
                <image class="protrusion_img" src="/static/menu.png" mode=""></image>
            </view>
        </template>
    </xz-tabBar>
</template>
<style lang="less" scoped>
.protrusion {
    position: absolute;
    width: 130rpx;
    height: 130rpx;
    border-radius: 50%;
    top: -50rpx;
    background-color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    .protrusion_img {
        width: 80%;
        height: 80%;
        border-radius: 50%;
    }
}
</style>

自定义样式

const tabBarStyle = {
    height: '100rpx',
    left: '20rpx',
    right: '20rpx',
    bottom: '20rpx',
    borderRadius: '10rpx'
};
<xz-tabBar :list="list" pageKey="user" safeAreaShowType="margin" :tabBarStyle="tabBarStyle" selectColor="#1296db" @openPage="openPage"></xz-tabBar>

注意事项:

  1. 使用自定义tabBar会遮住页面底部一个tabBar的高度,需要页面添加下边距或者使用scroll-view组件更好的完成页面效果。
  2. 虽然自定义tabBar添加了隐藏系统tabBar,但还是需要在App.vue自行添加uni.hideTabBar(),以提高体验感。
  3. 可能会闪屏,如果建议自行解决

官方注意事项:自定义tabBar的性能体验会低于原生tabBar。App和小程序端非必要不要自定义。

  • H5端的自定义tabBar组件:H5端不存在原生tabBar性能更高的概念,并且宽屏下常见的tabBar在顶部而不是底部,此时可以使用 custom-tab-bar组件来自定义
  • 普通自定义tabBar:使用view自行绘制tabBar。如果页面是多页方式,切换tabBar将无法保持底部tabBar一直显示。所以这种情况建议使用单页方式。单页方式,如果是复杂页面,应用性能会下降明显,需减少页面复杂度。如果是App端,nvue单页的性能会显著高于vue页面
  • 微信小程序自定义tabbar:微信提供一直基于webview自定义tabBar的方案。该功能体验不佳,不太推荐使用。
  • 原生的tabbar有且只有一个且在首页。二级页如需的tab,需自行编写view来实现。一般二级页面更适合的导航是 segement组件

scroll-view配合自定义tabBar以及自定义导航

<script lang="ts" setup>
import { onBeforeMount, ref, watch } from 'vue';

/**
 * @property {String} title 页面标题
 * @property {String} pageKey 页面key
 * @property {String} navBarHeight 如果用插槽自定义导航栏则需要传入其高度
 * @property {String} background 页面背景颜色
 */
interface Prop {
    title: string;
    pageKey: string;
    navBarHeight: string;
    background: string;
}
const props = withDefaults(defineProps<Prop>(), {});

// 隐藏tabBar
onBeforeMount(() => {
    uni.hideTabBar();
});

const list = [
    {
        text: '首页',
        pageKey: 'calendar',
        pagePath: '/pages/home/index',
        iconPath: '/static/tabBar/home.png',
        selectedIconPath: '/static/tabBar/home.png'
    },
    {
        text: '我的',
        pageKey: 'user',
        pagePath: '/pages/user/index',
        iconPath: '/static/tabBar/user.png',
        selectedIconPath: '/static/tabBar/user_select.png'
    }
];

const openPage = (url: string) => {
    uni.switchTab({
        url
    });
};

// 计算页面高度
let scrollHeight = ref<number>(0);
let navBarHeight = ref<number>(0);
let tabBarHeight = ref<number>(0);
const getNavHeight = (height: number) => {
    navBarHeight.value = height;
};
const getTabHeight = (height: number) => {
    tabBarHeight.value = height;
};

watch(
    () => props.navBarHeight,
    (newVal) => {
        if (newVal != '0') navBarHeight.value = Number(newVal);
    },
    {
        deep: true,
        immediate: true
    }
);
</script>

<template>
    <view class="page_common" :style="{ background }">
        <!-- navBar -->
        <slot name="navBar" v-if="$slots.navBar"></slot>
        <xz-navBar v-else :navBarStyle="{ position: 'relative' }" :title="props.title" @getNavHeight="getNavHeight"></xz-navBar>
        <!-- 主体内容 -->
        <scroll-view scroll-y :style="{ height: `calc(100vh - ${navBarHeight + tabBarHeight}px)` }">
            <view class="page_content">
                <slot></slot>
            </view>
        </scroll-view>
        <!-- tabBar -->
        <xz-tabBar
            :tabBarStyle="{ position: 'relative' }"
            :list="list"
            :pageKey="props.pageKey"
            color="#444444"
            selectColor="#00B386"
            tabBarTopType="shadow"
            @openPage="openPage"
            @getTabHeight="getTabHeight"
        ></xz-tabBar>
    </view>
</template>

<style lang="scss" scoped>
.page_common {
    height: 100vh;
    overflow: hidden;
    background-color: rgba(238, 238, 238, 0.2);

    .page_content {
        overflow: hidden;
        box-sizing: border-box;
    }
}
</style>

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议