Skip to content

Tabs 标签页

分隔内容上有关联但属于不同类别的数据集合。

ts
import { createApp } from 'vue'
import { TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'

const app = createApp()
app.use(ElTabPane)
app.use(ElTabs)

基础用法

基础的、简洁的标签页。

<template>
  <el-tabs v-model="activeName" class="demo-tabs">
    <el-tab-pane label="默认选项1" name="first">默认选项1</el-tab-pane>
    <el-tab-pane label="默认选项2" name="second">默认选项2</el-tab-pane>
    <el-tab-pane label="默认选项3" name="third">默认选项3</el-tab-pane>
    <el-tab-pane label="默认选项4" name="fourth">默认选项4</el-tab-pane>
  </el-tabs>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'


const activeName = ref('first')
</script>

<style>
.demo-tabs > .el-tabs__content {
  padding: 16px;
  color: var(--dh-color-text-secondary);
  font-size: var(--dh-font-size-base);
  font-weight: var(--dh-font-weight-regular);
}
</style>

卡片风格的标签

你可以设置具有卡片风格的标签。

<template>
  <el-tabs
    v-model="activeName"
    type="card"
    class="demo-tabs"
  >
    <el-tab-pane label="默认选项1" name="first">默认选项1</el-tab-pane>
    <el-tab-pane label="默认选项2" name="second">默认选项2</el-tab-pane>
    <el-tab-pane label="默认选项3" name="third">默认选项3</el-tab-pane>
    <el-tab-pane label="默认选项4" name="fourth">默认选项4</el-tab-pane>
  </el-tabs>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'


const activeName = ref('first')
</script>

<style>
.demo-tabs > .el-tabs__content {
  padding: 16px;
  color: var(--dh-color-text-secondary);
  font-size: var(--dh-font-size-base);
  font-weight: var(--dh-font-weight-regular);
}
</style>

带有边框的卡片风格

你还可以设置标签页为带有边框的卡片

<script setup lang="ts">
import { TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'

</script>

<template>
  <el-tabs type="border-card">
    <el-tab-pane label="默认选项1">默认选项1</el-tab-pane>
    <el-tab-pane label="默认选项2">默认选项2</el-tab-pane>
    <el-tab-pane label="默认选项3">默认选项3</el-tab-pane>
    <el-tab-pane label="默认选项4">默认选项4</el-tab-pane>
  </el-tabs>
</template>

标签位置的设置

可以通过 tab-position 设置标签的位置

<template>
  <el-radio-group v-model="tabPosition" style="margin-bottom: 30px">
    <el-radio-button value="top">top</el-radio-button>
    <el-radio-button value="right">right</el-radio-button>
    <el-radio-button value="bottom">bottom</el-radio-button>
    <el-radio-button value="left">left</el-radio-button>
  </el-radio-group>

  <el-tabs :tab-position="tabPosition" style="height: 200px" class="demo-tabs">
    <el-tab-pane label="User">User</el-tab-pane>
    <el-tab-pane label="Config">Config</el-tab-pane>
    <el-tab-pane label="Role">Role</el-tab-pane>
    <el-tab-pane label="Task">Task</el-tab-pane>
  </el-tabs>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import type { TabsInstance } from '@szhn/dh-design-pc'
import { RadioButton as ElRadioButton, RadioGroup as ElRadioGroup, TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'


const tabPosition = ref<TabsInstance['tabPosition']>('left')
</script>

<style>
.demo-tabs > .el-tabs__content {
  padding: 32px;
  color: #6b778c;
  font-size: 32px;
  font-weight: 600;
}

.el-tabs--right .el-tabs__content,
.el-tabs--left .el-tabs__content {
  height: 100%;
}
</style>

自定义标签页的内容

可以通过具名插槽来实现自定义标签页的内容

<template>
  <el-tabs type="border-card" class="demo-tabs">
    <el-tab-pane>
      <template #label>
        <span class="custom-tabs-label">
          <el-icon><calendar /></el-icon>
          <span>Route</span>
        </span>
      </template>
      Route
    </el-tab-pane>
    <el-tab-pane label="Config">Config</el-tab-pane>
    <el-tab-pane label="Role">Role</el-tab-pane>
    <el-tab-pane label="Task">Task</el-tab-pane>
  </el-tabs>
</template>

<script lang="ts" setup>
import { Calendar } from '@szhn/dh-design-pc/icons'
import { Icon as ElIcon, TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'

</script>

<style>
.demo-tabs > .el-tabs__content {
  padding: 32px;
  color: #6b778c;
  font-size: 32px;
  font-weight: 600;
}
.demo-tabs .custom-tabs-label .el-icon {
  vertical-align: middle;
}
.demo-tabs .custom-tabs-label span {
  vertical-align: middle;
  margin-left: 4px;
}
</style>

动态增减标签页

增减标签页按钮只能在选项卡样式的标签页下使用

<template>
  <el-tabs
    v-model="editableTabsValue"
    type="card"
    editable
    class="demo-tabs"
    @edit="handleTabsEdit"
  >
    <el-tab-pane
      v-for="item in editableTabs"
      :key="item.name"
      :label="item.title"
      :name="item.name"
    >
      {{ item.content }}
    </el-tab-pane>
  </el-tabs>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import type { TabPaneName } from '@szhn/dh-design-pc'
import { TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'


let tabIndex = 2
const editableTabsValue = ref('2')
const editableTabs = ref([
  {
    title: 'Tab 1',
    name: '1',
    content: 'Tab 1 content',
  },
  {
    title: 'Tab 2',
    name: '2',
    content: 'Tab 2 content',
  },
])

const handleTabsEdit = (
  targetName: TabPaneName | undefined,
  action: 'remove' | 'add'
) => {
  if (action === 'add') {
    const newTabName = `${++tabIndex}`
    editableTabs.value.push({
      title: 'New Tab',
      name: newTabName,
      content: 'New Tab content',
    })
    editableTabsValue.value = newTabName
  } else if (action === 'remove') {
    const tabs = editableTabs.value
    let activeName = editableTabsValue.value
    if (activeName === targetName) {
      tabs.forEach((tab, index) => {
        if (tab.name === targetName) {
          const nextTab = tabs[index + 1] || tabs[index - 1]
          if (nextTab) {
            activeName = nextTab.name
          }
        }
      })
    }

    editableTabsValue.value = activeName
    editableTabs.value = tabs.filter((tab) => tab.name !== targetName)
  }
}
</script>

<style>
.demo-tabs > .el-tabs__content {
  padding: 32px;
  color: #6b778c;
  font-size: 32px;
  font-weight: 600;
}
</style>

添加按钮自定义图标 (2.4.0)

<template>
  <el-tabs
    v-model="editableTabsValue"
    type="card"
    class="demo-tabs"
    editable
    @edit="handleTabsEdit"
  >
    <template #add-icon>
      <el-icon><select-icon /></el-icon>
    </template>
    <el-tab-pane
      v-for="item in editableTabs"
      :key="item.name"
      :label="item.title"
      :name="item.name"
    >
      {{ item.content }}
    </el-tab-pane>
  </el-tabs>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { Select as SelectIcon } from '@szhn/dh-design-pc/icons'
import type { TabPaneName } from '@szhn/dh-design-pc'
import { Icon as ElIcon, Select as ElSelect, TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'


let tabIndex = 2
const editableTabsValue = ref('2')
const editableTabs = ref([
  {
    title: 'Tab 1',
    name: '1',
    content: 'Tab 1 content',
  },
  {
    title: 'Tab 2',
    name: '2',
    content: 'Tab 2 content',
  },
])

const handleTabsEdit = (
  targetName: TabPaneName | undefined,
  action: 'remove' | 'add'
) => {
  if (action === 'add') {
    const newTabName = `${++tabIndex}`
    editableTabs.value.push({
      title: 'New Tab',
      name: newTabName,
      content: 'New Tab content',
    })
    editableTabsValue.value = newTabName
  } else if (action === 'remove') {
    const tabs = editableTabs.value
    let activeName = editableTabsValue.value
    if (activeName === targetName) {
      tabs.forEach((tab, index) => {
        if (tab.name === targetName) {
          const nextTab = tabs[index + 1] || tabs[index - 1]
          if (nextTab) {
            activeName = nextTab.name
          }
        }
      })
    }

    editableTabsValue.value = activeName
    editableTabs.value = tabs.filter((tab) => tab.name !== targetName)
  }
}
</script>

<style>
.demo-tabs > .el-tabs__content {
  padding: 32px;
  color: #6b778c;
  font-size: 32px;
  font-weight: 600;
}
</style>

增加标签页触发器自定义

<template>
  <div style="margin-bottom: 20px">
    <el-button size="small" @click="addTab(editableTabsValue)">
      add tab
    </el-button>
  </div>
  <el-tabs
    v-model="editableTabsValue"
    type="card"
    class="demo-tabs"
    closable
    @tab-remove="removeTab"
  >
    <el-tab-pane
      v-for="item in editableTabs"
      :key="item.name"
      :label="item.title"
      :name="item.name"
    >
      {{ item.content }}
    </el-tab-pane>
  </el-tabs>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import type { TabPaneName } from '@szhn/dh-design-pc'
import { Button as ElButton, TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'


let tabIndex = 2
const editableTabsValue = ref('2')
const editableTabs = ref([
  {
    title: 'Tab 1',
    name: '1',
    content: 'Tab 1 content',
  },
  {
    title: 'Tab 2',
    name: '2',
    content: 'Tab 2 content',
  },
])

const addTab = (targetName: string) => {
  const newTabName = `${++tabIndex}`
  editableTabs.value.push({
    title: 'New Tab',
    name: newTabName,
    content: 'New Tab content',
  })
  editableTabsValue.value = newTabName
}
const removeTab = (targetName: TabPaneName) => {
  const tabs = editableTabs.value
  let activeName = editableTabsValue.value
  if (activeName === targetName) {
    tabs.forEach((tab, index) => {
      if (tab.name === targetName) {
        const nextTab = tabs[index + 1] || tabs[index - 1]
        if (nextTab) {
          activeName = nextTab.name
        }
      }
    })
  }

  editableTabsValue.value = activeName
  editableTabs.value = tabs.filter((tab) => tab.name !== targetName)
}
</script>

<style>
.demo-tabs > .el-tabs__content {
  padding: 32px;
  color: #6b778c;
  font-size: 32px;
  font-weight: 600;
}
</style>

默认值 (2.11.9)

<template>
  <el-tabs
    v-model="activeName"
    class="demo-tabs"
    default-value="third"
    @tab-click="handleClick"
  >
    <el-tab-pane
      v-for="tab in tabs"
      :key="tab.name"
      :label="tab.label"
      :name="tab.name"
    >
      default-value: third
      <br />
      active: {{ activeName }}
    </el-tab-pane>
  </el-tabs>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import type { TabsPaneContext } from '@szhn/dh-design-pc'
import { TabPane as ElTabPane, Tabs as ElTabs } from '@szhn/dh-design-pc'


const tabs = ref([
  { label: 'User', name: 'first' },
  { label: 'Config', name: 'second' },
  { label: 'Role', name: 'third' },
  { label: 'Task', name: 'fourth' },
])

const activeName = ref()

const handleClick = (tab: TabsPaneContext, event: Event) => {
  console.log(tab, event)
}
</script>

<style>
.demo-tabs > .el-tabs__content {
  padding: 32px;
  color: #6b778c;
  font-size: 32px;
  font-weight: 600;
}
</style>

Tabs API

Tabs Attributes

属性名说明类型Default
model-value / v-model绑定值,选中选项卡的 name,默认值是第一个 tab 的 namestring / number
default-value 2.11.9在初始渲染时处于激活状态的标签的值。 (避免初始化时变动)string / number
type风格类型enum''
closable标签是否可关闭booleanfalse
addable标签是否可增加booleanfalse
editable标签是否同时可增加和关闭booleanfalse
tab-position选项卡所在位置enumtop
stretch标签的宽度是否自撑开booleanfalse
before-leave切换标签之前的钩子函数, 若返回 false 或者返回被 reject 的 Promise,则阻止切换。Function() => true
tabindex 2.11.7tabs 的 tabindexstring / number0

Tabs Events

事件名说明回调参数
tab-clicktab 被选中时触发Function
tab-changeactiveName 改变时触发Function
tab-remove点击 tab 移除按钮时触发Function
tab-add点击 tab 新增按钮时触发Function
edit点击 tab 的新增或移除按钮后触发Function

Tabs Slots

插槽名说明子标签
default默认插槽Tab-pane
add-icon 2.5.4自定义添加按钮图标
addIcon 2.4.0 deprecated自定义添加按钮图标

Tabs Exposes

方法名说明类型
currentName当前活动的面板名称object
tabNavRef 2.9.10tab-nav 组件实例object

Tab-nav API

Tab-nav Exposes

方法名说明类型
scrollToActiveTab滚动到活动标签Function
removeFocus移除聚焦状态Function
tabListRef 2.9.10el_tabs__nav html 元素object
tabBarRef 2.9.10el_tabs__nav bar 实例object

Tab-bar API

Tab-bar Exposes

属性名详情类型
ref 2.9.10选项卡根 HTML 元素object
update 2.9.10手动更新标签栏样式的方法,返回更新后的样式Function

Tab-pane API

Tab-pane Attributes

名称详情Type默认值
label选项卡标题string''
disabled是否禁用booleanfalse
name与选项卡绑定值 value 对应的标识符,表示选项卡别名。默认值是tab面板的序列号,如第一个 tab 是 0string / number
closable标签是否可关闭booleanfalse
lazy标签是否延迟渲染booleanfalse

Tab-pane Slots

NameDescription
defaultTab-pane 的内容
labelTab-pane 的标题内容

常见问题

我们已对外暴露了实现该功能所需的必要能力。 您可以查看 示例 来用原生的方式实现。 或使用 SortableJs, 示例