Skip to content

Tabs 标签页

当内容较多需要对内容进行分类,可使用标签页来展示各项分类内容,标签页和导航有点类似,只是在内容层级上有所区别,标签页属于更详细的内容分类

组件注册

js
import { FTabs } from '@fesjs/fes-design';

app.use(FTabs);

代码演示

基础用法

默认选中第一项。

play
<template>
    <FTabs @change="handleChange" @clickTab="handleClickTab">
        <FTabPane name="T恤" value="T恤">
            <div class="tab-content">T恤</div>
        </FTabPane>
        <FTabPane name="卫衣啊卫衣" value="卫衣" displayDirective="show">
            <div class="tab-content">卫衣</div>
        </FTabPane>
        <FTabPane name="衬衫" value="衬衫">
            <div class="tab-content">衬衫</div>
        </FTabPane>
    </FTabs>
</template>

<script lang="ts" setup>
const handleChange = (value: string | number) => {
    console.log('[tabs.common] handleChange, value:', value);
};
const handleClickTab = (value: string | number) => {
    console.log('[tabs.common] handleClickTab, value:', value);
};
</script>

<style scoped>
.tab-content {
    background: #fff;
    line-height: 60px;
    text-align: center;
}
</style>

禁用

禁用某一项。

play
<template>
    <FTabs>
        <FTabPane name="T恤" value="T恤">
            <div class="tab-content">T恤</div>
        </FTabPane>
        <FTabPane name="卫衣" value="卫衣" disabled>
            <div class="tab-content">卫衣</div>
        </FTabPane>
        <FTabPane name="衬衫" value="衬衫">
            <div class="tab-content">衬衫</div>
        </FTabPane>
    </FTabs>
</template>

<style scoped>
.tab-content {
    background: #fff;
    line-height: 60px;
    text-align: center;
}
</style>

图标

有图标的标签。

play
<template>
    <FTabs>
        <FTabPane value="微笑">
            <template #tab>
                <span class="my-tab"><UserOutlined />&nbsp;微笑</span>
            </template>
            <div class="tab-content">微笑</div>
        </FTabPane>
        <FTabPane value="等待">
            <template #tab>
                <span class="my-tab"><ClockCircleOutlined />&nbsp;等待</span>
            </template>
            <div class="tab-content">等待</div>
        </FTabPane>
    </FTabs>
</template>

<style scoped>
.tab-content {
    background: #fff;
    line-height: 60px;
    text-align: center;
}

.my-tab {
    display: flex;
    align-items: center;
}
</style>

展示指令

可以制定标签页展示的指令为 if 、 show 或者 show:lazy 。使用 show 的时候标签页内容不会随着切换重置。使用 show:lazy 的时候显示效果跟 show 一致,不过内容会进行延迟加载。

play
<template>
    <FTabs>
        <FTabPane name="show" displayDirective="show" value="show">
            <FInput
                style="margin-top: 20px"
                placeholder="切换tab内容不会被重置"
            />
        </FTabPane>
        <FTabPane name="show2" displayDirective="show" value="show2">
            <FInput
                style="margin-top: 20px"
                placeholder="切换tab内容不会被重置"
            />
        </FTabPane>
        <FTabPane name="if" displayDirective="if" value="if">
            <FInput style="margin-top: 20px" placeholder="切换tab内容被重置" />
        </FTabPane>
        <FTabPane
            name="show:lazy"
            displayDirective="show:lazy"
            value="show:lazy"
        >
            <FInput
                style="margin-top: 20px"
                placeholder="延迟加载,并且之后的切换内容不会重置"
            />
        </FTabPane>
    </FTabs>
</template>

位置

指定标签的位置,position = 'left' | 'top' | 'right' | 'bottom'

play
<template>
    <FRadioGroup
        v-model="position"
        :cancelable="false"
        :options="
            ['top', 'bottom', 'left', 'right'].map((i) => ({
                label: i,
                value: i,
            }))
        "
    />
    <FDivider />

    <FTabs :position="position" style="height: 300px">
        <FTabPane v-for="i in 20" :key="i" :name="`Tab ${i}`" :value="i">
            <div class="tab-content">Tab {{ i }}</div>
        </FTabPane>
    </FTabs>
</template>

<script setup>
import { ref } from 'vue';

const position = ref('left');
</script>

<style scoped>
.tab-content {
    background: #fff;
    line-height: 300px;
    text-align: center;
}
</style>

前缀 & 后缀

使用 prefix、suffix slot 来添加前后缀。

play
<template>
    <FForm>
        <FFormItem label="位置:">
            <FRadioGroup
                v-model="position"
                :cancelable="false"
                :options="
                    ['top', 'bottom', 'left', 'right'].map((i) => ({
                        label: i,
                        value: i,
                    }))
                "
            />
        </FFormItem>
        <FFormItem label="展示前缀:">
            <FSwitch v-model="showPrefix" />
        </FFormItem>
        <FFormItem label="展示后缀:">
            <FSwitch v-model="showSuffix" />
        </FFormItem>
    </FForm>
    <FDivider />

    <FTabs :position="position" style="height: 300px">
        <FTabPane
            v-for="i in 2"
            :key="i"
            :name="`Tab ${i}`"
            :value="i"
            closable
        >
            <div class="tab-content">Tab {{ i }}</div>
        </FTabPane>
        <template v-if="showPrefix" #prefix>Prefix</template>
        <template v-if="showSuffix" #suffix>Suffix</template>
    </FTabs>
</template>

<script setup>
import { ref } from 'vue';

const position = ref('left');
const showPrefix = ref(true);
const showSuffix = ref(true);
</script>

<style scoped>
.tab-content {
    background: #fff;
    line-height: 60px;
    text-align: center;
}
</style>

卡片式页签

另一种样式的页签,仅支持 position = 'top'

play
<template>
    <FTabs type="card">
        <FTabPane name="T恤" value="T恤">
            <div class="tab-content">T恤</div>
        </FTabPane>
        <FTabPane name="卫衣" value="卫衣">
            <div class="tab-content">卫衣</div>
        </FTabPane>
        <FTabPane name="衬衫" value="衬衫">
            <div class="tab-content">衬衫</div>
        </FTabPane>
    </FTabs>
</template>

<style scoped>
.tab-content {
    background: #fff;
    line-height: 60px;
    text-align: center;
}
</style>

可关闭或增加页签

卡片式页签,设置了可删除后,hover 时显示删除按钮

play
<template>
    <FTabs
        v-model="activeTab"
        type="card"
        addable
        closable
        @close="handleCloseTab"
        @add="handleAddTab"
        @change="handleChangeTab"
    >
        <FTabPane
            v-for="(tab, index) in tabs"
            :key="index"
            :name="tab"
            :closable="tab !== '卫衣'"
            :value="index"
        >
            <div class="tab-content">{{ tab }}</div>
        </FTabPane>
    </FTabs>
</template>

<script>
import { reactive, ref } from 'vue';

export default {
    setup() {
        const tabs = reactive(['T恤', '卫衣', '衬衫', '夹克']);
        const activeTab = ref(0);

        function handleCloseTab(key) {
            tabs.splice(key, 1);
            if (activeTab.value === key) {
                activeTab.value
                    = key >= tabs.length - 1 ? tabs.length - 1 : key;
            } else if (activeTab.value > key) {
                activeTab.value = activeTab.value - 1;
            }
        }

        function handleAddTab() {
            tabs.push(`New Tab${tabs.length + 1}`);
            activeTab.value = tabs.length - 1;
        }
        const handleChangeTab = (key) => {
            console.log('[tabs.closable] [handleChangeTab] key:', key);
        };
        return {
            tabs,
            activeTab,
            handleCloseTab,
            handleAddTab,
            handleChangeTab,
        };
    },
};
</script>

<style scoped>
.tab-content {
    background: #fff;
    line-height: 60px;
    text-align: center;
}
</style>

使用配置

play
<template>
    <FTabs :panes="tabPanes" />
</template>

<script setup>
import { h } from 'vue';

const render = (param) =>
    h(
        'div',
        {
            style: {
                background: '#fff',
                lineHeight: '60px',
                textAlign: 'center',
            },
        },
        [param.name],
    );
const tabPanes = [
    { name: 'T恤', value: 'T恤', render },
    { name: '卫衣啊卫衣', value: '卫衣', render },
    { name: '衬衫', value: '衬衫', render, renderTab: () => '衬衫99' },
];
</script>

Tabs Props

属性说明类型默认值
modelValue当前激活 tab 面板的 keynumber / string-
position页签位置,可选值有left top right bottomstringtop
type页签的基本样式,可选card linestringline
closable页签是否可关闭,type 为card时可用booleanfalse
closeMode关闭显示的方式,可选hover visiblestringvisible
transition自定义页签切换过渡 TransitionGroup 的动画名。默认是 true,使用内置过渡动画string/booleantrue
panes配置页签TabPaneProps[][]

Tabs Events

事件名称说明回调参数
close页签关闭按钮点击回调(key) => {}
change切换 tab 时回调(key) => {}
clickTab点击 tab 时回调(key) => {}

Tabs Slots

名称说明
defaultTabPane 页签面板
prefixtabs 的前置内容
suffixtabs 的后置内容

TabPane Props

属性说明类型默认值
valuetab 的值string / number-
nametab 的名称string / number-
disabled是否禁用booleanfalse
closable是否可关闭booleanfalse
displayDirective选择渲染使用的指令为 if 、 show 或者 show:lazy。使用 show 的时候标签页内容不会随着切换重置。使用 show:lazy 的时候显示效果跟 show 一致,不过内容会进行延迟加载。stringif
render自定义内容,仅在配置 panes 中有效(props: TabProps) => VNodeChild-
renderTab自定义页签,,仅在配置 panes 中有效(props: TabProps) => VNodeChild-

TabPane Slots

名称说明
defaultTabPane 内容
tab标签项 tab 的内容