Tab - Vant 4
Tab
Intro
Used to switch between different content areas.
Install
Register component globally via app.use, refer to Component Registration for more registration ways.
import { createApp } from'vue'; import { Tab, Tabs } from'vant'; const app = createApp(); app.use(Tab); app.use(Tabs);Usage
Basic Usage
The first tab is active by default, you can set v-model:active to active specified tab.
import { ref } from'vue'; exportdefault { setup() { const active = ref(0); return { active }; }, };Match By Name
import { ref } from'vue'; exportdefault { setup() { const activeName = ref('b'); return { activeName }; }, };Swipe Tabs
By default more than 5 tabs, you can scroll through the tabs. You can set swipe-threshold attribute to customize threshold number.
Disabled Tab
Use disabled prop to disable a tab.
Card Style
Tabs styled as cards.
Click Event
import { showToast } from'vant'; exportdefault { setup() { constonClickTab = ({ title }) => showToast(title); return { onClickTab, }; }, };Sticky
In sticky mode, the tab nav will be fixed to top when scroll to top.
Shrink
In shrink mode, the tabs will be shrinked to the left.
Custom Tab
Use title slot to custom tab title.
Switch Animation
Use animated props to change tabs with animation.
Swipeable
In swipeable mode, you can switch tabs with swipe gesture in the content.
Scrollspy
In scrollspy mode, the list of content will be tiled.
Before Change
import { ref } from'vue'; exportdefault { setup() { const active = ref(0); constbeforeChange = (index) => { // prevent changeif (index === 1) { returnfalse; } // asyncreturnnewPromise((resolve) => { setTimeout(() =>resolve(index !== 3), 1000); }); }; return { active, beforeChange, }; }, };Tips: The before-change callback will not be triggered by swiping gesture.
Hide Header
By setting the showHeader prop to false, the title bar of the Tabs component can be hidden. In this case, you can control the active prop of the Tabs using custom components.
API
Tabs Props
| Attribute | Description | Type | Default |
|---|---|---|---|
| v-model:active | Index of active tab | *number | string* |
| type | Can be set to line``card | string | line |
| color | Tab color | string | #1989fa |
| background | Background color | string | white | | duration | Toggle tab's animation time | number | string | 0.3 | | line-width | Width of tab line | number | string | 40px | | line-height | Height of tab line | number | string | 3px | | animated | Whether to change tabs with animation (After enabling this attribute, if there is a sticky layout in the content area, it will not meet expectations) | boolean | false | | border | Whether to show border when type="line" | boolean | false | | ellipsis | Whether to ellipsis too long title (Takes effect only if shrink is false and the number of tabs is less than or equal to swipe-threshold) | boolean | true | | sticky | Whether to use sticky mode | boolean | false | | shrink | Whether to shrink the the tabs to the left | boolean | false | | swipeable | Whether to enable gestures to slide left and right (After enabling this attribute, if there is a sticky layout in the content area, it will not meet expectations) | boolean | false | | lazy-render | Whether to enable tab content lazy render | boolean | true | | scrollspy | Whether to use scrollspy mode | boolean | false | | show-header v4.7.3 | Whether to show title bar | boolean | true | | offset-top | Sticky offset top , supports px``vw``vh``rem unit, default px | number | string | 0 | | swipe-threshold | Set swipe tabs threshold (Takes effect only when shrink is false and ellipsis is true) | number | string | 5 | | title-active-color | Title active color | string | - | | title-inactive-color | Title inactive color | string | - | | before-change | Callback function before changing tabs, return false to prevent change, support return Promise | (name: number | string) => boolean | Promise<boolean> | - |
Tab Props
| Attribute | Description | Type | Default |
|---|---|---|---|
| title | Title | string | - |
| disabled | Whether to disable tab | boolean | false |
| dot | Whether to show red dot on the title | boolean | false |
| badge | Content of the badge on the title (Effective when dot is false) | *number | string* |
| name | Identifier | *number | string* |
| url | Link | string | - |
| to | The target route should navigate to when clicked on, same as the to prop of Vue Router | *string | object* |
| replace | If true, the navigation will not leave a history record | boolean | false | | title-style | Custom title style | string | Array | object | - | | title-class | Custom title class name | string | Array | object | - | | show-zero-badge | Whether to show badge when the value is zero | boolean | true |
Tabs Events
| Event | Description | Arguments |
|---|---|---|
| click-tab | Emitted when a tab is clicked | *{ name: string |
| change | Emitted when active tab changed | *name: string |
| rendered | Emitted when content first rendered in lazy-render mode | *name: string |
| scroll | Emitted when tab scrolling in sticky mode | { scrollTop: number, isFixed: boolean } |
Tabs Methods
Use ref to get Tabs instance and call instance methods.
| Name | Description | Attribute | Return value |
|---|---|---|---|
| resize | Resize Tabs when container element resized or visibility changed | - | - |
| scrollTo | Go to specified tab in scrollspy mode | *name: string | number* |
Types
The component exports the following type definitions:
importtype { TabProps, TabsType, TabsProps, TabsInstance } from'vant';TabsInstance is the type of component instance:
import { ref } from'vue'; importtype { TabsInstance } from'vant'; const tabsRef = ref<TabsInstance>(); tabsRef.value?.scrollTo(0);Tabs Slots
| Name | Description |
|---|---|
| nav-left | Custom nav left content |
| nav-right | Custom nav right content |
| nav-bottom | Custom nav bottom content |
Tab Slots
| Name | Description |
|---|---|
| default | Content of tab |
| title | Custom tab title |
Theming
CSS Variables
The component provides the following CSS variables, which can be used to customize styles. Please refer to ConfigProvider component.
| Name | Default Value | Description |
|---|---|---|
| --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) | - |
FAQ
After Tabs enable the swipeable or animated attribute, the sticky function of content area elements will not meet expectations
When the swipeable or animated attribute is enabled for Tabs, the content area will be wrapped by an element with the transform attribute, and if the sticky function is enabled for the element in the content area, the function will take effect, but the display position will not be as expected.
For example, the following code:
This is because the fixed positioning inside the transform element is computed relative to that element, not relative to the entire document, resulting in layout exceptions.
How to determine if the current component is inside an active Tab?
In a child component, you can use useTabStatus or useAllTabStatus to check whether the component is inside an active Tab.
useTabStatus: Returns whether the current component's parentTabis active. Returnsnullif the component is not inside aTab.useAllTabStatus: In nested Tab scenarios, returns whether all parentTabsare active. Returnsnullif the component is not inside aTab.
const isActive = useTabStatus(); // For nested Tab scenariosconst isAllActive = useAllTabStatus();