TabBar 底部导航栏
移动端底部路由级导航。图标 + 标签 + 徽标;line/fill 两种激活样式;iOS 安全区适配。
English translation pending This page hasn't been translated yet — falling back to Chinese. PRs welcome on GitHub.
基础用法
CfTabBar 是手机 app 底部的路由切换栏。每个 item 必须有 key 和图标;label 可选(纯图标也合法)。默认 fixed 贴底、safeArea 在 iOS 上补 padding-bottom。受控传 v-model / value+onChange,外接 vue-router / react-router 来切页面。
背景 视口
<script setup lang="ts">
import { ref } from 'vue';
import { CfTabBar, type TabBarItem } from '@chufix-design/vue';
const active = ref('home');
const items: TabBarItem[] = [
{ key: 'home', label: '首页', iconPath: 'M12 3l9 8h-3v10h-4v-6h-4v6H6V11H3z' },
{ key: 'discover', label: '发现', iconPath: 'M12 2a10 10 0 100 20 10 10 0 000-20zm3.5 6.5L14 13l-4.5 1.5L11 10z' },
{ key: 'inbox', label: '消息', iconPath: 'M4 4h16v12H7l-3 3V4z', badge: 3 },
{ key: 'me', label: '我的', iconPath: 'M12 12a4 4 0 100-8 4 4 0 000 8zm-7 8a7 7 0 0114 0H5z' },
];
</script>
<template>
<div class="demo-scope">
<CfTabBar v-model="active" :items="items" :fixed="false" />
<p class="demo-hint">当前:<code>{{ active }}</code> — 真实使用时设 <code>fixed</code> 为 true 贴底,并启用 <code>safeArea</code>。</p>
</div>
</template>
<style scoped>
.demo-scope { background: var(--bg-1); border-radius: var(--r-6); overflow: hidden; }
.demo-hint { padding: 12px 16px; margin: 0; color: var(--fg-3); }
</style> <script setup>
import { ref } from 'vue';
import { CfTabBar } from '@chufix-design/vue';
const active = ref('home');
const items= [
{ key: 'home', label: '首页', iconPath: 'M12 3l9 8h-3v10h-4v-6h-4v6H6V11H3z' },
{ key: 'discover', label: '发现', iconPath: 'M12 2a10 10 0 100 20 10 10 0 000-20zm3.5 6.5L14 13l-4.5 1.5L11 10z' },
{ key: 'inbox', label: '消息', iconPath: 'M4 4h16v12H7l-3 3V4z', badge: 3 },
{ key: 'me', label: '我的', iconPath: 'M12 12a4 4 0 100-8 4 4 0 000 8zm-7 8a7 7 0 0114 0H5z' },
];
</script>
<template>
<div class="demo-scope">
<CfTabBar v-model="active" :items="items" :fixed="false" />
<p class="demo-hint">当前:<code>{{ active }}</code> — 真实使用时设 <code>fixed</code> 为 true 贴底,并启用 <code>safeArea</code>。</p>
</div>
</template>
<style scoped>
.demo-scope { background: var(--bg-1); border-radius: var(--r-6); overflow: hidden; }
.demo-hint { padding: 12px 16px; margin: 0; color: var(--fg-3); }
</style> import { useState } from 'react';
import { CfTabBar } from '@chufix-design/react';
export default function Demo() {
const [active, setActive] = useState('home');
const items: TabBarItem[] = [
{ key: 'home', label: '首页', iconPath: 'M12 3l9 8h-3v10h-4v-6h-4v6H6V11H3z' },
{ key: 'discover', label: '发现', iconPath: 'M12 2a10 10 0 100 20 10 10 0 000-20zm3.5 6.5L14 13l-4.5 1.5L11 10z' },
{ key: 'inbox', label: '消息', iconPath: 'M4 4h16v12H7l-3 3V4z', badge: 3 },
{ key: 'me', label: '我的', iconPath: 'M12 12a4 4 0 100-8 4 4 0 000 8zm-7 8a7 7 0 0114 0H5z' },
];
return (
<>
<div className="demo-scope">
<CfTabBar value={active} onChange={setActive} items={items} fixed={false} />
<p className="demo-hint">当前:<code>{active}</code> — 真实使用时设 <code>fixed</code> 为 true 贴底,并启用 <code>safeArea</code>。</p>
</div>
</>
);
} import { useState } from 'react';
import { CfTabBar } from '@chufix-design/react';
export default function Demo() {
const [active, setActive] = useState('home');
const items= [
{ key: 'home', label: '首页', iconPath: 'M12 3l9 8h-3v10h-4v-6h-4v6H6V11H3z' },
{ key: 'discover', label: '发现', iconPath: 'M12 2a10 10 0 100 20 10 10 0 000-20zm3.5 6.5L14 13l-4.5 1.5L11 10z' },
{ key: 'inbox', label: '消息', iconPath: 'M4 4h16v12H7l-3 3V4z', badge: 3 },
{ key: 'me', label: '我的', iconPath: 'M12 12a4 4 0 100-8 4 4 0 000 8zm-7 8a7 7 0 0114 0H5z' },
];
return (
<>
<div className="demo-scope">
<CfTabBar value={active} onChange={setActive} items={items} fixed={false} />
<p className="demo-hint">当前:<code>{active}</code> — 真实使用时设 <code>fixed</code> 为 true 贴底,并启用 <code>safeArea</code>。</p>
</div>
</>
);
} 与 Tabs 的区别
CfTabs 是”内容区切换”,多个 <CfTabPanel> 配合;CfTabBar 是”应用路由切换”,固定贴底、不包含内容面板。两者语义和定位都不同。
CfTabBar | CfTabs | |
|---|---|---|
| 角色 | 路由 / 应用主导航 | 内容分组 |
| 定位 | 底部 fixed(默认) | 内联 |
| 与 router | 外接 | 内部 v-model |
| 触摸热区 | ≥ --touch-target-min(48px) | 桌面尺寸 |
API
| 属性 | 类型 | 默认 | 说明 |
|---|---|---|---|
items | TabBarItem[] | — | 导航项列表 |
modelValue (Vue) / value (React) | string | — | 当前 key |
fixed | boolean | true | position: fixed 贴底 |
safeArea | boolean | true | 加 padding-bottom: var(--safe-area-bottom) |
variant | 'line' | 'fill' | 'line' | 激活样式 |
ariaLabel | string | '主导航' | 无障碍标签 |
TabBarItem
| 字段 | 类型 | 说明 |
|---|---|---|
key | string | 唯一标识 |
label | string? | 文字(可省略) |
iconPath | string? | SVG path data(最轻量) |
icon | ReactNode? (React) / slot icon-{key} (Vue) | 自定义图标节点 |
badge | number | string? | 角标;falsy 时隐藏 |
disabled | boolean? | 禁用 |
反馈与讨论
TabBar 底部导航栏 · Discussion