s***@aliyun.com
s***@aliyun.com
  • 发布:2026-06-13 09:30
  • 更新:2026-06-13 09:30
  • 阅读:17

uniapp x 自定义+动态Tabbar+自定义tabbar 支持服务端动态配置的自定义Tabbar(tabbar切换无闪烁问题)

分类:uni-app x

sunrains-tabbar 自定义 TabBar 插件使用指南

📋 目录


1. 基础配置

1.1 创建 tabbar-config.uts 文件

在项目根目录创建 tabbar-config.uts 文件,用于注册全局组件和配置导航栏。

完整示例:

// 1. 导入所有自定义 tabbar 页面组件并注册  
import Recommend from '@/pages/home/recommend.uvue'  
import Order from '@/pages/order/order.uvue'  
import Mine from '@/pages/mine/mine.uvue'  
import {   
  setNavbarConfig,   
  NavBarConfig,   
  registerGlobalComponent,   
  setDefaultTabItems,   
  TabItem   
} from '@/uni_modules/sunrains-tabbar/types.uts'  

// 2. 注册全局组件  
registerGlobalComponent('home', Recommend)  
registerGlobalComponent('order', Order)  
registerGlobalComponent('mine', Mine)  

// 3. 配置导航栏(可选,不设置会使用默认配置)  
setNavbarConfig(new NavBarConfig(  
  true,       // 是否显示导航栏  
  17,         // 字体大小  
  'bold',     // 字体粗细  
  '#333333',  // 文字颜色  
  '#ffffff',  // 背景颜色  
  '',         // 标题  
  56,         // 高度  
  44          // 内容高度  
))  

// 4. 设置默认 Tab 列表(至少设置一个固定项)  
// 其他 Tab 可通过服务端接口动态配置  
setDefaultTabItems([  
  new TabItem(  
    'home',                              // 唯一标识  
    '首页',                              // 显示名称  
    '/static/tab/main1.png',             // 未选中图标  
    '/static/tab/main1_active.png',      // 选中图标  
    '@/pages/home/recommend.uvue',       // 页面路径  
    Recommend                            // 组件引用  
  ),  
  new TabItem(  
    'mine',  
    '我的',  
    '/static/tab/main3.png',  
    '/static/tab/main3_active.png',  
    '@/pages/mine/mine.uvue',  
    Mine  
  )  
])

关键步骤说明:

  1. 导入组件:将所有需要作为 Tab 的页面组件导入
  2. 注册组件:使用 registerGlobalComponent 注册每个组件(第一个参数为唯一标识)
  3. 配置导航栏:可选配置,根据项目需求调整
  4. 设置默认 Tab:至少配置一个固定 Tab,其余可动态添加

2. pages.json 配置

2.1 必需配置

必须在 pages.json 中配置自定义 TabBar 入口页面(必须放在第一个位置):

{  
  "path": "uni_modules/sunrains-tabbar/index",  
  "style": {  
    "navigationBarTitleText": "自定义tabbar",  
    "navigationStyle": "custom"  
  }  
}

2.2 完整示例

{  
  "pages": [  
    {  
      "path": "uni_modules/sunrains-tabbar/index",  
      "style": {  
        "navigationBarTitleText": "自定义tabbar",  
        "navigationStyle": "custom"  
      }  
    },  
    {  
      "path": "pages/home/recommend",  
      "style": {  
        "navigationBarTitleText": "首页"  
      }  
    },  
    {  
      "path": "pages/mine/mine",  
      "style": {  
        "navigationBarTitleText": "我的"  
      }  
    },  
    {  
      "path": "pages/order/order",  
      "style": {  
        "navigationBarTitleText": "订单"  
      }  
    },  
    {  
      "path": "pages/detail/detail",  
      "style": {  
        "navigationBarTitleText": "详情"  
      }  
    }  
  ],  
  "globalStyle": {  
    "backgroundColor": "#ffffff"  
  }  
}

注意事项:

  • 自定义 TabBar 入口页面必须配置在 pages 数组的第一位
  • 所有 Tab 页面都需要在 pages 中声明
  • navigationStyle 设置为 "custom" 以隐藏原生导航栏

3. 动态配置 TabBar

3.1 使用场景

当需要根据用户权限、服务端配置等动态调整 TabBar 时,可以在任意页面触发刷新。

3.2 实现示例

mine.uvue 页面为例:

<template>  
  <view class="mine-page"  >  
    <view class="page-title">  
      <text class="title-text">动态设置中心</text>  
    </view>  
    <scroll-view direction="vertical" style="height: 90%;">  
      <view class="tabbar">  
        <text class="title-text">tabbar设置</text>  
        <button class="tabbar-btn" @click="refresh1">动态tabbar(我的)</button>  
        <button class="tabbar-btn" @click="refresh2">动态tabbar(首页、我的)</button>  
        <button class="tabbar-btn" @click="refresh3">动态tabbar(订单、我的)</button>  
        <button class="tabbar-btn" @click="refresh4">动态tabbar(我的、订单、首页)</button>  
        <text class="title-text">tabbar背景色、高度设置</text>  
        <input class="input-item" v-model="bgColor"  placeholder="请输入背景色(例:#ffffff)" />  
        <input class="input-item" v-model="tabHeight"   placeholder="请输入高度(例:50)" />  
        <button class="tabbar-btn" @click="setStyle">确定</button>  
      </view>  
    </scroll-view>  
  </view>  
</template>  

<script setup lang="uts">  
  import { ref } from 'vue'  
  import {SYSTEM} from "@/uni_modules/sunrains-tabbar/utssdk/system.uts"  
  import { TabItem, GLOBAL_COMPONENT_REGISTRY } from '@/uni_modules/sunrains-tabbar/utssdk/types.uts'  
  const bgColor = ref<string>('pink')  
  const tabHeight = ref<string>('120')  
   const ss = ref<any>("");  
  function setStyle(){  
      uni.$emit('setTabbarStyle',{"color":bgColor.value,"height":parseInt(tabHeight.value)})  
  }  

  function refresh1() {  
    console.log("动态tabbar(我的)")  
    uni.$emit('refreshNewTabbar', [  
      new TabItem('mine', '我的', '/static/tab/main3.png', '/static/tab/main3_active.png', '@/pages/mine/mine.uvue', GLOBAL_COMPONENT_REGISTRY.get('mine') as any)  
    ])  
  }  
  function refresh2() {  
    console.log("动态tabbar(首页、我的)")  
    uni.$emit('refreshNewTabbar', [  
      new TabItem('home', '首页', '/static/tab/main1.png', '/static/tab/main1_active.png', '@/pages/home/recommend.uvue', GLOBAL_COMPONENT_REGISTRY.get('home') as any),  
      new TabItem('mine', '我的', '/static/tab/main3.png', '/static/tab/main3_active.png', '@/pages/mine/mine.uvue', GLOBAL_COMPONENT_REGISTRY.get('mine') as any)  
    ])  
  }  
  function refresh3() {  
    console.log("动态tabbar(订单、我的)")  
    uni.$emit('refreshNewTabbar', [  
      new TabItem('order', '订单', '/static/tab/main2.png', '/static/tab/main2_active.png', '@/pages/order/order.uvue', GLOBAL_COMPONENT_REGISTRY.get('order') as any),  
      new TabItem('mine', '我的', '/static/tab/main3.png', '/static/tab/main3_active.png', '@/pages/mine/mine.uvue', GLOBAL_COMPONENT_REGISTRY.get('mine') as any)  
    ])  
  }  
  function refresh4() {  
    console.log("动态tabbar(我的、订单、首页)")  
    uni.$emit('refreshNewTabbar', [  
      new TabItem('mine', '我的', '/static/tab/main3.png', '/static/tab/main3_active.png', '@/pages/mine/mine.uvue', GLOBAL_COMPONENT_REGISTRY.get('mine') as any),  
      new TabItem('order', '订单', '/static/tab/main2.png', '/static/tab/main2_active.png', '@/pages/order/order.uvue', GLOBAL_COMPONENT_REGISTRY.get('order') as any),  
      new TabItem('home', '首页', '/static/tab/main1.png', 'https://gimg3.baidu.com/search/src=https%3A%2F%2Fpic.rmb.bdstatic.com%2Fbjh%2Fuser%2F779083e57f84a4ce5345b17aaf7f8459.jpeg&refer=http%3A%2F%2Fwww.baidu.com&app=2021&size=r1,1&n=0&g=4&er=404&q=100&maxorilen2heic=2000000?sec=1781283600&t=4feca8b5a1149e3ed0f28ee030f767b4', '@/pages/home/recommend.uvue', GLOBAL_COMPONENT_REGISTRY.get('home') as any)  
    ])  
  }  
</script>  

<style scoped lang="scss">  
  .mine-page {  
    height: 100%;  

    margin: 20px;  
  }  

  .page-title {  
    font-size: 120px;  
    color: #333;  
    margin-bottom: 15px;  
    display: flex;  
    align-items: center;  
    justify-content: center;  
    font-weight: 600;  
    width: 100%;  
  }  

  .title-text {  
    font-size: 18px !important;  
    font-weight: bold !important;  
    color: #333 !important;  
  }  

  .tabbar {  
    // border: 2px solid cyan;  
    padding: 15px;  
    display: flex;  
    flex-direction: column;  
  }  

  .input-item {  
    height: 45px;  
    border: 1px solid #ccc;  
    border-radius: 6px;  
    padding-left: 10px;  
    background: #fff;  
    margin : 10px;  
    padding-left: 20px;  
  }  

  .tabbar-btn {  
    margin-bottom: 10px;  
    border-radius: 8px;  
    background: #f5f5f5;  
    border: 1px solid #e5e5e5;  
    padding: 16px 0;  
    font-size: 16px;  
  }  

  .tabbar-btn:last-child {  
    margin-bottom: 0;  
  }  
</style>  

关键点:

  • 使用 uni.$emit('refreshNewTabbar', [...]) 触发 TabBar 刷新
  • 通过 GLOBAL_COMPONENT_REGISTRY.get('key') 获取已注册的组件
  • 确保所有动态 Tab 对应的组件已在 tabbar-config.uts 中注册

4. 小程序端特殊配置

4.1 配置 tab-content-renderer.uvue

注意: 仅在需要支持微信小程序时需要配置,App 端可忽略此步骤。

uni_modules/sunrains-tabbar/tab-content-renderer.uvue 中配置:

<template>  
  <view class="renderer-wrap">  
    <!-- App 端:使用动态组件 -->  
    <!-- #ifndef MP-WEIXIN -->  
    <template v-for="item in items" :key="item.key">  
      <component  
        v-if="currentTab === item.key"  
        :is="item.component"  
        :key="`${item.key}-${renderKey}`"  
      />  
    </template>  
    <!-- #endif -->  

    <!-- 微信小程序端:使用静态声明 -->  
    <!-- #ifdef MP-WEIXIN -->  
    <Recommend v-if="currentTab === 'home'" style="width: 100%; height: 100%;" />  
    <Order v-if="currentTab === 'order'" style="width: 100%; height: 100%;" />  
    <Mine v-if="currentTab === 'mine'" style="width: 100%; height: 100%;" />  
    <!-- #endif -->  
  </view>  
</template>  

<script setup lang="uts">  
import { TabItem } from './utssdk/types.uts'  

// #ifdef MP-WEIXIN  
// 只有在小程序端才需要这些导入,App 端会自动忽略  
import Recommend from '@/pages/home/recommend.uvue'  
import Order from '@/pages/order/order.uvue'  
import Mine from '@/pages/mine/mine.uvue'  
// #endif  

interface Props {  
  currentTab: string  
  items: TabItem[]  
  renderKey: number  
}  

defineProps<Props>()  
</script>  

<style scoped>  
.renderer-wrap {  
  width: 100%;  
  height: 100%;  
}  
</style>

配置说明:

  1. 条件编译:使用 #ifndef MP-WEIXIN#ifdef MP-WEIXIN 区分平台
  2. App 端:使用 <component :is="..."> 动态渲染组件
  3. 小程序端:必须静态导入并声明所有可能的 Tab 组件
  4. 导入位置:在 #ifdef MP-WEIXIN 块内导入组件

⚠️ 常见问题

Q1: 为什么小程序端需要单独配置?

A: 微信小程序不支持动态组件渲染,必须静态声明所有可能使用的组件。

Q2: 动态 Tab 刷新失败怎么办?

A: 检查以下几点:

  • 组件是否在 tabbar-config.uts 中正确注册
  • 是否正确使用了 GLOBAL_COMPONENT_REGISTRY.get() 获取组件
  • TabItem 的参数是否完整且类型正确

Q3: 导航栏配置不生效?

A: 确保 setNavbarConfig()setDefaultTabItems() 之前调用,或在应用启动时尽早调用。


📝 总结

  1. 基础配置三要素:注册组件 → 配置导航栏 → 设置默认 Tab
  2. pages.json:自定义 TabBar 入口必须放在第一位
  3. 动态刷新:通过 uni.$emit('refreshNewTabbar', [...]) 实现
  4. 小程序兼容:需要在 tab-content-renderer.uvue 中静态声明组件
0 关注 分享

要回复文章请先登录注册