Tabs 分頁
同層內容切換。嚴格對齊 WAI-ARIA APG tabs pattern:tablist/tab/tabpanel 三角色關聯 + roving tabindex + 方向鍵導覽。
基礎用法
基礎用法
水墨散文內容。
vue
<script setup lang="ts">
</script>
<template>
<LhTabs>
<LhTabPane name="prose" label="散文">水墨散文内容。</LhTabPane>
<LhTabPane name="poem" label="诗词">诗词格律内容。</LhTabPane>
<LhTabPane name="calligraphy" label="书法">书法碑帖内容。</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {}
</script>
<template>
<LhTabs>
<LhTabPane name="prose" label="散文">水墨散文内容。</LhTabPane>
<LhTabPane name="poem" label="诗词">诗词格律内容。</LhTabPane>
<LhTabPane name="calligraphy" label="书法">书法碑帖内容。</LhTabPane>
</LhTabs>
</template>卡片外觀與停用
卡片外觀與停用
墨分五色。
vue
<script setup lang="ts">
</script>
<template>
<LhTabs type="card">
<LhTabPane name="ink" label="墨">墨分五色。</LhTabPane>
<LhTabPane name="cinnabar" label="朱" disabled>丹砂不可用。</LhTabPane>
<LhTabPane name="gold" label="金">藤黄点染。</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {}
</script>
<template>
<LhTabs type="card">
<LhTabPane name="ink" label="墨">墨分五色。</LhTabPane>
<LhTabPane name="cinnabar" label="朱" disabled>丹砂不可用。</LhTabPane>
<LhTabPane name="gold" label="金">藤黄点染。</LhTabPane>
</LhTabs>
</template>底部位置
底部位置
山勢渾厚。
vue
<script setup lang="ts">
</script>
<template>
<LhTabs tab-position="bottom">
<LhTabPane name="mountain" label="山">山势浑厚。</LhTabPane>
<LhTabPane name="water" label="水">水意空灵。</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {}
</script>
<template>
<LhTabs tab-position="bottom">
<LhTabPane name="mountain" label="山">山势浑厚。</LhTabPane>
<LhTabPane name="water" label="水">水意空灵。</LhTabPane>
</LhTabs>
</template>可關閉與可新增
可關閉與可新增
第一卷內容。
vue
<script setup lang="ts">
import { ref } from 'vue'
const panes = ref([
{ name: 's1', label: '画卷一', content: '第一卷内容。', disabled: false },
{ name: 's2', label: '画卷二', content: '第二卷内容。', disabled: false },
])
let index = 2
const removePane = (name) => {
const target = panes.value.find((pane) => pane.name === name)
if (target) panes.value.splice(panes.value.indexOf(target), 1)
}
const addPane = () => {
index += 1
panes.value.push({ name: `s${index}`, label: `画卷${index}`, content: '新卷内容。', disabled: false })
}
</script>
<template>
<!-- 可關閉與可新增 -->
<LhTabs closable addable tab-position="bottom" @tab-remove="removePane" @tab-add="addPane">
<LhTabPane
v-for="pane in panes"
:key="pane.name"
:name="pane.name"
:label="pane.label"
:disabled="pane.disabled"
>{{ pane.content }}</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {
data() {
return {
panes: [
{ name: 's1', label: '画卷一', content: '第一卷内容。', disabled: false },
{ name: 's2', label: '画卷二', content: '第二卷内容。', disabled: false },
],
index: 2,
}
},
methods: {
removePane(name) {
const target = this.panes.find((pane) => pane.name === name)
if (target) this.panes.splice(this.panes.indexOf(target), 1)
},
addPane() {
this.index += 1
this.panes.push({ name: `s${this.index}`, label: `画卷${this.index}`, content: '新卷内容。', disabled: false })
},
},
}
</script>
<template>
<!-- 可關閉與可新增 -->
<LhTabs closable addable tab-position="bottom" @tab-remove="removePane" @tab-add="addPane">
<LhTabPane
v-for="pane in panes"
:key="pane.name"
:name="pane.name"
:label="pane.label"
:disabled="pane.disabled"
>{{ pane.content }}</LhTabPane>
</LhTabs>
</template>關閉啟用分頁時元件會連動切換到相鄰可用分頁,並發出
tab-remove;由使用方負責從資料來源移除對應 pane。
受控用法
受控用法
水墨內容。
當前分頁:mo
vue
<script setup lang="ts">
import { ref } from 'vue'
const active = ref('mo')
</script>
<template>
<LhTabs v-model="active" type="card">
<LhTabPane name="zh" label="国风">国风内容。</LhTabPane>
<LhTabPane name="mo" label="水墨">水墨内容。</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {
data() {
return { active: 'mo' }
},
}
</script>
<template>
<LhTabs v-model="active" type="card">
<LhTabPane name="zh" label="国风">国风内容。</LhTabPane>
<LhTabPane name="mo" label="水墨">水墨内容。</LhTabPane>
</LhTabs>
</template>Tabs API
LhTabs Props
| 屬性名 | 說明 | 類型 | 預設值 |
|---|---|---|---|
| modelValue | 當前啟用分頁的 name(v-model) | string | — |
| type | 外觀 | "line" | "card" | 'line' |
| closable | 分頁是否可關閉 | boolean | false |
| addable | 是否顯示新增按鈕 | boolean | false |
| tabPosition | 分頁位置 | "top" | "bottom" | 'top' |
| sx | sx 快速版面配置屬性 | LhSxProps | — |
LhTabs Events
| 事件名 | 說明 | 回呼參數 |
|---|---|---|
| update:modelValue | 啟用分頁變化(v-model) | (name: string) |
| tab-change | 啟用分頁變化 | (name: string) |
| tab-remove | 分頁關閉 | (name: string) |
| tab-add | 點選新增按鈕 | — |
LhTabPane Props
| 屬性名 | 說明 | 類型 | 預設值 |
|---|---|---|---|
| name | 分頁唯一標識(穩定鍵,不建議動態修改) | string | — |
| label | 分頁標題 | string | '' |
| disabled | 是否停用 | boolean | false |
Slots
| 插槽名 | 說明 | 作用元件 |
|---|---|---|
| default | 分頁面板(LhTabPane 列表) | LhTabs |
| default | 面板內容 | LhTabPane |
無障礙
嚴格對齊 WAI-ARIA APG tabs pattern:
- 分頁頭為
role="tablist",每個分頁為role="tab"(aria-selected+aria-controls),面板為role="tabpanel"(aria-labelledby+tabindex="0") - roving tabindex:僅啟用分頁可 Tab 聚焦,其餘為
tabindex="-1" - 方向鍵在可用分頁間移動並自動啟用(跳過停用項),Home/End 跳到首尾
closable時按 Delete 鍵關閉當前分頁;關閉圖示為aria-hidden裝飾,鍵盤走 Delete,避免按鈕巢狀按鈕- 停用分頁不可聚焦啟用,
tab-remove等操作對停用項無效
類型定義
本元件對外匯出的 TypeScript 類型結構如下(自動提取自 packages/components/tabs/src/types.ts 與 @lh-ui/share/core/* 原始碼,點選各條目展開檢視完整定義;屬性說明見上方 Props 表):
LhTabsProps
ts
export interface LhTabsProps {
/** 當前啟用分頁的 name(v-model) */
modelValue?: string
/** 外觀 */
type?: LhTabsType
/** 分頁是否可關閉 */
closable?: boolean
/** 是否顯示新增按鈕 */
addable?: boolean
/** 分頁位置 */
tabPosition?: LhTabsPosition
/** sx 快速版面配置屬性 */
sx?: LhSxProps
}LhTabPaneProps
ts
export interface LhTabPaneProps {
/** 分頁唯一標識(作為穩定鍵,不建議動態修改) */
name: string
/** 分頁標題 */
label?: string
/** 是否停用 */
disabled?: boolean
}LhTabsType (來自 @lh-ui/share/core/tabs)
ts
/**
* 分頁外觀
*/
export type LhTabsType = 'line' | 'card'LhTabsPosition (來自 @lh-ui/share/core/tabs)
ts
/**
* 分頁位置
*/
export type LhTabsPosition = 'top' | 'bottom'