Tab 标签页 - Vant 4
Tab タブ 📑
紹介
🎯 Tab タブ はとても実用的なタブコンポーネントです。本の目次のように、異なるコンテンツ領域を簡単に切り替えられます。商品分類やニュースカテゴリ、設定ページの各オプションなど、UI を整然と保ち、優れた体験を提供します。
取り込み
以下の方法でコンポーネントをグローバル登録します。詳細はコンポーネント登録を参照してください。
import { createApp } from 'vue';
import { Tab, Tabs } from 'vant';
const app = createApp();
app.use(Tab);
app.use(Tabs);コード例
基本的な使い方 🚀
最も簡単な使い方!v-model:active で現在のタブのインデックス/名前をバインドし、デフォルトでは最初のタブが有効です。まるで本をめくるように!
import { ref } from'vue'; exportdefault { setup() { const active = ref(0); return { active }; }, };名前でマッチング 🏷️
より厳密に管理したい場合は、各タブに固有の name を指定しましょう。v-model:active の値はその name になり、読みやすくなります。
<van-tabs v-model:active="activeName">
<van-tab title="タブ 1" name="a">コンテンツ 1</van-tab>
<van-tab title="タブ 2" name="b">コンテンツ 2</van-tab>
<van-tab title="タブ 3" name="c">コンテンツ 3</van-tab>
</van-tabs>import { ref } from 'vue';
export default {
setup() {
const activeName = ref('b');
return { activeName };
},
};タブバーのスクロール 📱
タブが多すぎる場合は?心配無用!タブが 5 個を超えると自動的に横スクロールが有効になり、切り替え時には現在のタブを中央に表示します。
<van-tabs v-model:active="active">
<van-tab v-for="index in 8" :title="`タブ ${index}`">
コンテンツ {{ index }}
</van-tab>
</van-tabs>タブの無効化 🚫
一部のタブを押せなくしたい場合は、disabled を設定して簡単に無効化できます。
<van-tabs v-model:active="active">
<van-tab title="タブ 1">コンテンツ 1</van-tab>
<van-tab title="タブ 2" disabled>タブ 2</van-tab>
<van-tab title="タブ 3">コンテンツ 3</van-tab>
</van-tabs>スタイル 🎨
Tab は柔軟に2種類のスタイルに対応:クラシックな line と、カード風の card。デフォルトは line、type で簡単に切り替え可能です。
<van-tabs v-model:active="active" type="card">
<van-tab title="タブ 1">コンテンツ 1</van-tab>
<van-tab title="タブ 2">コンテンツ 2</van-tab>
<van-tab title="タブ 3">コンテンツ 3</van-tab>
</van-tabs>クリックイベント 👆
ユーザーがどのタブをクリックしたかを知りたい?click-tab イベントが役立ちます。クリックごとに発火し、即応できます。
import { ref } from'vue'; import { showToast } from'vant'; exportdefault { setup() { const active = ref(0); constonClickTab = ({ title }) => showToast(title); return { active, onClickTab, }; }, };スティッキー配置 📌
タブバーを常に視界に保ちたい?sticky を有効化しましょう。ページスクロール時に上部に「貼り付き」、いつでも切り替え可能です。
<van-tabs v-model:active="active" sticky>
<van-tab title="タブ 1">コンテンツ 1</van-tab>
<van-tab title="タブ 2">コンテンツ 2</van-tab>
<van-tab title="タブ 3">コンテンツ 3</van-tab>
</van-tabs>💡 ヒント: ページ上部に他の要素(ナビバーなど)がある場合は、
offset-topで距離を調整して重なりを回避しましょう。
収縮レイアウト 📏
タブを幅いっぱいにしたくない場合は、shrink で収縮レイアウトを有効化。タブは左側へ揃って整然と並びます。
<van-tabs v-model:active="active" shrink>
<van-tab title="タブ 1">コンテンツ 1</van-tab>
<van-tab title="タブ 2">コンテンツ 2</van-tab>
<van-tab title="タブ 3">コンテンツ 3</van-tab>
</van-tabs>カスタムタイトル 🎭
タブを個性的にしたい?title スロットで完全にカスタマイズ可能。アイコンやバッジ、小さなアニメーションも追加できます。
<van-tabs v-model:active="active">
<van-tab>
<template #title>
<van-icon name="more-o" />
自定义
</template>
内容 1
</van-tab>
<van-tab title="标签 2">内容 2</van-tab>
</van-tabs>切り替えアニメーション ✨
切り替えを滑らかにしたい?animated を有効化すると、ページをめくるような優雅なトランジションが有効になります。
<van-tabs v-model:active="active" animated>
<van-tab title="タブ 1">コンテンツ 1</van-tab>
<van-tab title="タブ 2">コンテンツ 2</van-tab>
<van-tab title="タブ 3">コンテンツ 3</van-tab>
</van-tabs>スワイプ切り替え 👈👉
より自然な操作感を求めるなら、swipeable を有効化。左右のスワイプでタブを切り替えられます。
<van-tabs v-model:active="active" swipeable>
<van-tab title="タブ 1">コンテンツ 1</van-tab>
<van-tab title="タブ 2">コンテンツ 2</van-tab>
<van-tab title="タブ 3">コンテンツ 3</van-tab>
</van-tabs>スクロールナビ 📜
長いコンテンツを表示する場合は、scrollspy を有効化。スクロール位置に応じて該当のタブが自動でハイライトされます。
<van-tabs v-model:active="active" scrollspy sticky>
<van-tab title="タブ 1">コンテンツ 1</van-tab>
<van-tab title="タブ 2">コンテンツ 2</van-tab>
<van-tab title="タブ 3">コンテンツ 3</van-tab>
</van-tabs>非同期切り替え ⏳
切り替え前にチェックや非同期処理が必要?before-change が役に立ちます。権限チェックや保存処理などを挟めます。
import { ref } from'vue'; exportdefault { setup() { const active = ref(0); constbeforeChange = (index) => { // 返回 false 表示阻止此次切换if (index === 1) { returnfalse; } // 返回 Promise 来执行异步逻辑returnnewPromise((resolve) => { // 在 resolve 函数中返回 true 或 falsesetTimeout(() =>resolve(index !== 3), 1000); }); }; return { beforeChange, }; }, };Tips: ジェスチャーによるスワイプでは
before-changeは発火しません。
タイトルバーの非表示
showHeader を false に設定すると、タイトルバーをレンダリングしません。この場合、カスタムコンポーネントで active を制御できます。
API
Tabs Props
| パラメータ | 説明 | タイプ | デフォルト値 |
|---|---|---|---|
| v-model:active | 🎯 現在選択されているタブの識別子をバインド | number | string | 0 |
| type | 🎨 スタイルタイプ、オプション値は card | string | line |
| color | 🌈 タブのテーマカラー | string | #1989fa |
| background | 🎭 タブバーの背景色 | string | white |
| duration | ⏱️ アニメーション時間、単位は秒、0を設定するとアニメーションを無効にする | number | string | 0.3 |
| line-width | 📏 下部バーの幅、デフォルト単位は px | number | string | 40px |
| line-height | 📐 下部バーの高さ、デフォルト単位は px | number | string | 3px |
| animated | ✨ タブコンテンツの切り替え時のトランジションアニメーションを有効にするかどうか(この属性を有効にすると、コンテンツエリアにスティッキーレイアウトがある場合、期待通りに動作しない) | boolean | false |
| border | 🖼️ タブバーの外枠を表示するかどうか、type="line" の時のみ有効 | boolean | false |
| ellipsis | ✂️ 長すぎるタイトルテキストを省略するかどうか(shrink が false で、tab 数が swipe-threshold 以下の時のみ有効) | boolean | true |
| sticky | 📌 スティッキーレイアウトを使用するかどうか | boolean | false |
| shrink | 📏 左側収縮レイアウトを有効にするかどうか | boolean | false |
| swipeable | 👈👉 スワイプによる左右切り替えを有効にするかどうか(この属性を有効にすると、コンテンツエリアにスティッキーレイアウトがある場合、期待通りに動作しない) | boolean | false |
| lazy-render | 🚀 遅延レンダリングを有効にするかどうか(初めてタブに切り替えた時にのみコンテンツレンダリングがトリガーされる) | boolean | true |
| scrollspy | 📜 スクロールスパイモードを有効にするかどうか | boolean | false |
show-header v4.7.3 | 👁️ タイトルバーを表示するかどうか | boolean | true |
| offset-top | 📍 スティッキーレイアウト時の上部との距離、px``vw``vh``rem 単位をサポート、デフォルトは px | number | string | 0 |
| swipe-threshold | 🎚️ スクロールしきい値、タブ数がしきい値を超え、かつ総幅がタブバーの幅を超えると横スクロールを開始(shrink が false かつ ellipsis が true の時のみ有効) | number | string | 5 |
| title-active-color | 🎨 タイトルのアクティブ状態の色 | string | - |
| title-inactive-color | 🎨 タイトルの非アクティブ状態の色 | string | - |
| before-change | ⏳ タブ切り替え前のコールバック関数、false を返すと切り替えを阻止、Promise の返却をサポート | (name: number | string) => boolean | Promise<boolean> | - |
Tab Props
| パラメータ | 説明 | タイプ | デフォルト値 |
|---|---|---|---|
| title | 📝 タイトル | string | - |
| disabled | 🚫 タブを無効にするかどうか | boolean | false |
| dot | 🔴 タイトルの右上に小さな赤い点を表示するかどうか | boolean | false |
| badge | 🏷️ アイコンの右上のバッジのコンテンツ(dot が false の時に有効) | number | string | - |
| name | 🏷️ タブ名、マッチングの識別子として使用 | number | string | タブのインデックス値 |
| url | 🔗 クリック時に遷移するリンク先 | string | - |
| to | 🧭 クリック時に遷移するルート先(Vue Router の to 相当) | string | object | - |
| replace | 🔄 遷移時に履歴を置換するか | boolean | false |
| title-style | 🎨 自定义标题样式 | string | Array | object | - |
| title-class | 🎭 自定义标题类名 | string | Array | object | - |
| show-zero-badge | 0️⃣ バッジが 0 の場合に表示するか | boolean | true |
Tabs Events
| イベント名 | 説明 | コールバック引数 |
|---|---|---|
| click-tab | 👆 タブクリックで発火 | { name: string | number, title: string, event: MouseEvent, disabled: boolean } |
| change | 🔄 アクティブタブが変化したとき発火 | name: string | number, title: string |
| rendered | 🎨 タブ内容が初回レンダリングされた時(遅延レンダリング時のみ) | name: string | number, title: string |
| scroll | 📜 スクロール時に発火(sticky モード時のみ) | { scrollTop: number, isFixed: boolean } |
ヒント:
clickとdisabledイベントは廃止されました。click-tabを使用してください。
Tabs 方法
ref 経由で Tabs インスタンスを取得しメソッドを呼び出せます。詳細はコンポーネントのインスタンスメソッド を参照してください。
| メソッド名 | 説明 | 引数 | 戻り値 |
|---|---|---|---|
| resize | 外側要素のサイズや表示状態が変化した際に再描画を行う | - | - |
| scrollTo | 指定のタブへスクロール(スクロールナビモードで有効) | *name: string | number* |
类型定义
コンポーネントは以下の型定義をエクスポートします:
importtype { TabProps, TabsType, TabsProps, TabsInstance } from'vant';TabsInstance はコンポーネントインスタンスの型です:
import { ref } from'vue'; importtype { TabsInstance } from'vant'; const tabsRef = ref<TabsInstance>(); tabsRef.value?.scrollTo(0);Tabs Slots
| 名前 | 説明 |
|---|---|
| nav-left | タブバー左側の内容 |
| nav-right | タブバー右側の内容 |
| nav-bottom | タブバー下部の内容 |
Tab Slots
| 名称 | 说明 |
|---|---|
| default | タブ内容 |
| title | カスタムタイトル |
テーマカスタマイズ 🎨
スタイル変数
コンポーネントは以下の CSS 変数を提供しており、スタイルのカスタマイズに使用できます。使用方法は ConfigProvider コンポーネント を参照してください。
| 名称 | デフォルト | 説明 |
|---|---|---|
| --van-tab-text-color | var(--van-gray-7) | 📝 タブ文字色 |
| --van-tab-active-text-color | var(--van-text-color) | ✨ アクティブ時文字色 |
| --van-tab-disabled-text-color | var(--van-text-color-3) | 🚫 無効時文字色 |
| --van-tab-font-size | var(--van-font-size-md) | 📏 文字サイズ |
| --van-tab-line-height | var(--van-line-height-md) | 📐 行の高さ |
| --van-tabs-default-color | var(--van-primary-color) | 🎨 タブバーのデフォルト色 |
| --van-tabs-line-height | 44px | 📏 タブバー高さ |
| --van-tabs-card-height | 30px | 🃏 カードスタイル高さ |
| --van-tabs-nav-background | var(--van-background-2) | 🎭 背景色 |
| --van-tabs-bottom-bar-width | 40px | 📏 ボトムバー幅 |
| --van-tabs-bottom-bar-height | 3px | 📐 ボトムバー高さ |
| --van-tabs-bottom-bar-color | var(--van-primary-color) | 🌈 ボトムバー色 |
よくある質問
非表示から表示に切り替えると、ボトムバー位置がずれる?
Tabs はマウント時に自身の幅を取得してボトムバー位置を計算します。最初に非表示の場合、幅が 0 となり位置計算ができません。
解決方法
方法1:表示制御に v-show を使っている場合は v-if に置き換えます。
方法2:コンポーネントの resize を呼び出して再描画します。
this.$refs.tabs.resize();Tabs で swipeable や animated を有効化すると、内容領域の sticky が期待通りに動作しない
swipeable または animated を有効化すると、内容領域は transform を持つ要素でラップされます。この状態で sticky を使用すると、機能は有効でも表示位置がずれます。
例えば以下のケース:
これは、transform 要素内部の fixed が、その要素を基準に計算されるためです。
現在のコンポーネントがアクティブな Tab 内かどうかを判定する方法?
子コンポーネントで useTabStatus や useAllTabStatus を呼び出すことで判定できます。
useTabStatus:現在のTabがアクティブかどうか。Tab外の場合はnulluseAllTabStatus:ネストしたTabがある場合に、全ての上位Tabがアクティブかどうか。Tab外の場合はnull
const isActive = useTabStatus();
// 嵌套 Tab 场景
const isAllActive = useAllTabStatus();関連ドキュメント 📚
ナビゲーションコンポーネント 🧭
- NavBar ナビバー - 上部ナビ(Tab と併用)
- Tabbar タブバー - ページ間の切り替え
- Sidebar サイドバー - 多階層に適したサイドナビ
- IndexBar インデックスバー - アルファベット索引
表示コンポーネント 📱
- NoticeBar 通知バー - メッセージ表示
- Progress 進捗バー - 進捗表示
- Badge バッジ - 数字や状態の表示
- Tag タグ - 内容ラベルと分類
フィードバックコンポーネント 💬
- Toast トースト - 操作フィードバック
- Dialog ダイアログ - 重要情報の確認
- Loading ローディング - ローディング表示
ツールコンポーネント 🔧
- ConfigProvider グローバル設定 - テーマ設定