Element Plus 如何用默认插槽自定义 Segmented 组件的选项内容?
【免费下载链接】element-plus🎉 A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus
在 Element Plus 中使用ElSegmented分段控制器时,每个选项默认只渲染options中取到的label文本。如果希望选项里展示图标、多行文字或其他自定义结构,官方文档给出的做法是通过组件的默认插槽来渲染选项内容。本文基于 Element Plus 文档的 “Custom Content” 章节和对应示例,说明如何接入这个插槽、插槽参数怎么用,以及如何验证选中逻辑没有被破坏。
默认插槽的机制
Segmented 的 Slots API 定义了唯一的插槽(见 docs/en-US/component/segmented.md):
| Name | Description | Type |
|---|---|---|
| default | option renderer | object,参数为{ item: Option } |
也就是说,默认插槽会为options中的每一项各渲染一次,插槽参数里的item就是当前这一项的原始 option 数据。从组件模板 packages/components/segmented/src/segmented.vue 可以看到插槽的使用位置:
<div :class="ns.e('item-label')"> <slot :item="item">{{ getLabel(item) }}</slot> </div>这里有两个可以直接用于判断的事实:
- 插槽的 fallback 内容是
getLabel(item),即不写插槽时按label键(或props配置的别名键)取文本展示;写了默认插槽后,选项展示完全由插槽内容决定。 - 选项的数量、选中态、禁用态仍然由
options和v-model驱动,插槽只替换“长什么样”,不参与“选中哪个”的逻辑。
完整示例:图标 + 文本的选项
下面是文档 Custom Content 示例的完整代码,每个选项展示一个图标和一行文本:
<template> <el-segmented v-model="value" :options="options"> <template #default="scope"> <div class="flex flex-col items-center gap-2 p-2"> <el-icon size="20"> <component :is="scope.item.icon" /> </el-icon> <div>{{ scope.item.label }}</div> </div> </template> </el-segmented> </template> <script lang="ts" setup> import { ref } from 'vue' import { Apple, Cherry, Grape, Orange, Pear, Watermelon, } from '@element-plus/icons-vue' const value = ref('Apple') const options = [ { label: 'Apple', value: 'Apple', icon: Apple }, { label: 'Cherry', value: 'Cherry', icon: Cherry }, { label: 'Grape', value: 'Grape', icon: Grape }, { label: 'Orange', value: 'Orange', icon: Orange }, { label: 'Pear', value: 'Pear', icon: Pear }, { label: 'Watermelon', value: 'Watermelon', icon: Watermelon }, ] </script>要点说明:
- 图标是普通的数据,直接放在 option 对象的
icon字段里,通过<component :is="scope.item.icon" />动态渲染。图标组件来自@element-plus/icons-vue(示例中的导入即为文档原样),需要自行安装该依赖;你自己的项目里也可以换成任意可被动态渲染的组件。 - 外层
div上的flex flex-col items-center gap-2 p-2是文档站点示例用于居中排版的工具类,只影响观感;换成你自己项目里的样式类即可,功能不依赖它们。 scope.item是原始 option 对象,label、value、icon等字段都直接从它上面取。如果选项里的键名和默认不同(例如后端返回name而不是label),文档提供了props属性(2.9.8 起)来重命名value/label/disabled三个键,但这只影响组件内部取值与禁用判断;插槽里展示什么仍然由你直接读scope.item决定。
验证选中逻辑仍然有效
自定义内容没有改变底层的选项模型,因此验证方式和普通用法一致,依据是 Segmented 文档 的 API 定义:
- 用
v-model绑定当前值(类型string | number | boolean),点击某个选项后,绑定值应变为该选项的value字段取值,而不是插槽里展示的任何文本或图标。 - 监听
change事件,参数类型(val: any) => void,文档说明“triggers when the selected value changes, the param is current selected value”,回调收到的就是当前选中项的value。 - 对比不使用插槽的 基础示例:
options只给字符串数组时,展示的就是字符串本身;换成上面的对象数组 + 默认插槽后,选项数量、选中高亮和disabled行为都仍由options数据决定——组件模板中每项对应一个隐藏的radioinput,选中与否由v-model与value是否相等判断(见 segmented.vue 中getSelected(item)的实现)。
限制与边界
options不能为空:根元素有v-if="options.length",没有选项时整个组件不渲染,插槽自然也不会出现。Option的类型声明为Record<string, any> | string | number | boolean(见 types.ts),所以简单场景下options也可以只是字符串数组,此时插槽参数item就是该字符串本身,取值方式要相应调整。- 默认插槽是“option renderer”,只负责选项内容;
size、block、direction(2.8.7 起支持vertical)、整体disabled这些组件级行为不受插槽影响,仍按各自属性工作。
参考文件
- 组件文档(含 Slots 表与 API):docs/en-US/component/segmented.md
- 自定义内容示例:docs/examples/segmented/custom-content.vue
- 组件模板实现:packages/components/segmented/src/segmented.vue
【免费下载链接】element-plus🎉 A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考