Element Plus Switch 组件完全指南:从基础用法到源码级实现原理 📅 发布时间:2026/9/11 0:06:34 👁 浏览次数: Element Plus Switch 组件完全指南从基础用法到源码级实现原理【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plusElement Plus 的ElSwitch组件用于在两个对立状态之间进行切换是表单场景中最常用的开关控件之一。本文以 docs/en-US/component/switch.md 官方文档为骨架结合 switch.vue 源码 与 switch.ts 类型定义系统讲解其全部用法、API 属性、事件、插槽与底层实现原理帮助你从会用进阶到懂原理。基础用法Basic usageSwitch 通过v-model绑定一个Boolean类型的变量即可完成双向绑定这也是最常用的场景。在 basic.vue 示例 中可以看到开关打开与关闭两个状态下的背景色由两个 CSS 变量决定--el-switch-on-color开启状态下的背景色--el-switch-off-color关闭状态下的背景色template el-switch v-modelvalue1 / el-switch v-modelvalue2 classml-2 style--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949 / /template script langts setup import { ref } from vue const value1 ref(true) const value2 ref(true) /script从样式源码 packages/theme-chalk/src/switch.scss 可以看到当组件处于checked状态时核心轨道.el-switch__core的background-color会取getCssVar(switch-on-color)即--el-switch-on-color未选中时背景色则为--el-switch-off-color。这两个 CSS 变量属于主题变量体系既可以在组件内联样式覆盖也可以在使用主题定制时全局调整。底层模型受控与非受控从源码角度理解model-value与active-value/inactive-value的匹配关系决定了开关的显示状态。在 switch.vue 中const isControlled ref(props.modelValue ! false) const actualValue computed(() { return isControlled.value ? props.modelValue : false }) const checked computed(() actualValue.value props.activeValue)checked的计算方式是严格相等比较只有当当前值 activeValue时开关才处于开启状态。同时如果初始传入的model-value既不等于active-value也不等于inactive-value源码会通过debugWarn输出警告并自动将值矫正为inactiveValueif (![props.activeValue, props.inactiveValue].includes(actualValue.value)) { debugWarn(COMPONENT_NAME, model-value must be active-value or inactive-value) emit(UPDATE_MODEL_EVENT, props.inactiveValue) // ... }这说明在开发中务必保证绑定的值只来源于active-value或inactive-value二者之一否则会收到警告并被强制归位。尺寸SizesSwitch 提供了large、default默认、small三种尺寸通过size属性控制见 sizes.vue 示例el-switch v-modelvalue sizelarge active-textOpen inactive-textClose / br / el-switch v-modelvalue active-textOpen inactive-textClose / br / el-switch v-modelvalue sizesmall active-textOpen inactive-textClose /尺寸的取值在 switch.ts 中通过isValidComponentSize校验器约束只允许 | large | default | small。需要注意的是Switch 的size会通过useFormSize()与所在el-form/el-form-item的size联动——当你设置了表单级尺寸而未显式指定 Switch 的size时开关会自动继承表单的尺寸这保证了表单内控件的一致性。文字描述Text description通过active-text与inactive-text属性可以为开关两个状态分别添加文字说明。参见 text-description.vue 示例el-switch v-modelvalue1 active-textPay by month inactive-textPay by year /在默认非inline-prompt模式下文字渲染在轨道两侧的独立标签区.el-switch__label--left/--right开启状态的文字在右侧、关闭状态的文字在左侧并且只有当前生效的一侧文字处于激活高亮状态源码中的labelLeftKls/labelRightKls通过ns.is(active, ...)控制。inline-prompt文字内嵌进滑块当希望文字直接显示在滑块内部时使用inline-prompt属性。此时需要注意官方文档与源码的明确限制仅渲染文字的第一个字符。从 switch.vue 的模板可以看到inline-prompt模式下内容走的是.el-switch__inner结构且官方示例如active-text完整展示多个内容实际展示出的效果是首字 省略。因此若状态文字超过 1 个字符如中文的是/否、英文的Y/N可以放心使用若必须展示完整文案请使用非inline-prompt的轨道两侧模式。自定义图标Custom iconsactive-icon与inactive-icon允许为开关两个状态指定图标两者都会覆盖对应的文字属性源码注释明确 overridesactive-text / overridesinactive-text。参见 custom-icons.vue 示例script setup langts import { ref } from vue import { Check, Close } from element-plus/icons-vue const value1 ref(true) const value2 ref(true) /script template el-switch v-modelvalue1 :active-iconCheck :inactive-iconClose / el-switch v-modelvalue2 classmt-2 stylemargin-left: 24px inline-prompt :active-iconCheck :inactive-iconClose / /template图标属性的取值类型为string | Component即IconPropType见 switch.ts你可以直接传入一个 SVG Vue 组件如上例的Check/Close传入一个已全局注册的组件名字符串。Element Plus 内置了丰富的图标库可前往 图标文档 挑选。模板中图标通过el-icon包装component :is...渲染因此在inline-prompt模式下图标也能完整显示在滑块内部不受仅渲染首字符限制的影响。扩展的值类型Extended value types默认情况下开关绑定的是布尔值但通过active-value与inactive-value你可以让开关承载Boolean、String或Number任意一种类型的值。参见 extended-value-types.vue 示例el-tooltip :contentSwitch value: value placementtop el-switch v-modelvalue style--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949 active-value100 inactive-value0 / /el-tooltip script langts setup import { ref } from vue const value ref(100) /script此时v-model绑定的就不再是布尔值而是开启时的100与关闭时的0。这与checked使用严格相等比较的实现是配套的——类型必须完全一致才能正确匹配。在 switch.ts 中activeValue默认true、inactiveValue默认false类型均允许[Boolean, String, Number]。这一能力在表单提交场景非常实用例如直接把开关值对应到接口约定的枚举字符串或数字无需在提交前再做一次布尔到具体值的转换。禁用状态Disabled添加disabled属性即可禁用开关见 disabled.vue 示例el-switch v-modelvalue1 disabled / el-switch v-modelvalue2 classml-2 /禁用后的开关透明度变为0.6见 switch.scss。值得注意的细节是禁用状态并不仅仅是 UI 层面的在 switch.vue 中switchDisabled由useFormDisabled计算得出它会同时考虑组件自身的disabled属性所在el-form/el-form-item的禁用状态loading状态也会强制禁用开关。同时模板中的原生input typecheckbox也会同步设置:disabledswitchDisabled保证键盘与鼠标都无法操作。加载状态Loading设置loading属性为true表示开关处于加载状态见 loading.vue 示例el-switch v-modelvalue1 loading / el-switch v-modelvalue2 loading classml-2 /加载状态下滑块.el-switch__action内部会渲染一个Loading旋转图标el-icon v-ifloadingloading //el-icon并且如上一节所述开关会同时进入禁用态避免用户在异步请求期间反复切换。loading通常与before-change配合使用——先置loading为true表示请求进行中请求结束后再复位。阻止切换Prevent switchingbefore-change属性允许在状态真正改变之前插入一道审批关卡。官方定义返回false或返回一个被 reject 的Promise都会阻止切换。参见 prevent-switching.vue 示例script setup langts import { ref } from vue import { ElMessage } from element-plus const value1 ref(false) const value2 ref(false) const loading1 ref(false) const loading2 ref(false) // 返回 true - 允许切换 const beforeChange1 (): Promiseboolean { loading1.value true return new Promise((resolve) { setTimeout(() { loading1.value false ElMessage.success(Switch success) return resolve(true) }, 1000) }) } // reject - 阻止切换 const beforeChange2 (): Promiseboolean { loading2.value true return new Promise((_, reject) { setTimeout(() { loading2.value false ElMessage.error(Switch failed) return reject(new Error(Error)) }, 1000) }) } /script template el-switch v-modelvalue1 :loadingloading1 :before-changebeforeChange1 / el-switch v-modelvalue2 classml-2 :loadingloading2 :before-changebeforeChange2 / /template源码级的执行逻辑before-change的判断逻辑在 switch.vue 的switchValue函数中const switchValue () { if (switchDisabled.value) return const { beforeChange } props if (!beforeChange) { handleChange() return } const shouldChange beforeChange() const isPromiseOrBool [ isPromise(shouldChange), isBoolean(shouldChange), ].includes(true) if (!isPromiseOrBool) { throwError( COMPONENT_NAME, beforeChange must return type Promiseboolean or boolean ) } // ... }关键点返回类型强校验beforeChange必须返回boolean或Promiseboolean否则组件会直接throwError属于运行时硬约束Promise 语义resolve(true)才执行切换reject会被捕获并debugWarn不会导致未处理的 Promise 异常而resolve(false)同样不切换同步 false直接返回false也能立即阻止切换handleChange()内部会依次发出update:model-value、change、input三个事件。这种先校验、后变更的模式非常适合需要权限校验、余额确认、二次弹窗确认等业务场景。自定义滑块图标Custom action icon^(2.3.9)active-action-icon与inactive-action-icon用于自定义滑块action内部显示的图标与作用于轨道的active-icon/inactive-icon在视觉位置上不同。参见 custom-action-icon.vue 示例script setup langts import { ref } from vue import { Hide, View } from element-plus/icons-vue const value1 ref(true) /script template el-switch v-modelvalue1 :active-action-iconView :inactive-action-iconHide / /template从 switch.vue 模板 可以看到.el-switch__action内的渲染优先级为loading加载图标 active-action / inactive-action 插槽 action-icon 属性即加载状态下始终显示 Loading 图标否则优先使用插槽其次才回退到active-action-icon/inactive-action-icon属性。自定义滑块插槽Custom action slot^(2.4.4)如果你需要的不是图标而是任意内容如文字、徽标、自定义图形可以使用active-action与inactive-action插槽。参见 custom-action-slot.vue 示例el-switch v-modelvalue1 template #active-action span classcustom-active-actionT/span /template template #inactive-action span classcustom-inactive-actionF/span /template /el-switch插槽内容将直接渲染在滑块内部其尺寸受.el-switch__action样式宽高均为滑块按钮尺寸约束因此自定义内容需要注意缩放与溢出控制。完整 API 参考以下 API 以 switch.md 官方文档为准并结合 switch.ts 源码中的默认值与校验逻辑补充说明。Attributes属性名说明类型默认值model-value / v-model绑定值必须与active-value或inactive-value之一相等默认布尔类型boolean / string / numberfalsedisabled是否禁用booleanfalseloading是否处于加载状态加载时同时禁用booleanfalsesize开关尺寸 / large / default / small跟随表单上下文width开关宽度number / stringinline-prompt图标或文字是否显示在滑块内部文字仅渲染第一个字符booleanfalseactive-icon开启状态图标覆盖active-textstring / Component—inactive-icon关闭状态图标覆盖inactive-textstring / Component—active-action-icon ^(2.3.9)开启状态滑块内图标string / Component—inactive-action-icon ^(2.3.9)关闭状态滑块内图标string / Component—active-text开启状态文字stringinactive-text关闭状态文字stringactive-value开启状态对应的值boolean / string / numbertrueinactive-value关闭状态对应的值boolean / string / numberfalsename原生 input 的 name 属性stringvalidate-event是否触发表单校验booleantruebefore-change状态改变前的钩子返回false或返回被 reject 的Promise时阻止切换() Promiseboolean / boolean—id原生 input 的 idstring—tabindex原生 input 的 tabindexstring / number—aria-label ^(a11y) ^(2.7.2)同原生 input 的aria-labelstring—active-color ^(deprecated)开启状态背景色已废弃改用 CSS 变量--el-switch-on-colorstringinactive-color ^(deprecated)关闭状态背景色已废弃改用 CSS 变量--el-switch-off-colorstringborder-color ^(deprecated)开关边框颜色已废弃改用 CSS 变量--el-switch-border-colorstringlabel ^(a11y) ^(deprecated)同原生 input 的aria-label已废弃使用aria-labelstring—说明width属性在源码中通过addUnit(props.width)注入.el-switch__core的width内联样式见 switch.vue因此传60与60px均合法传入数值时宽度会随尺寸变大文字区域会自动以省略号截断示例中width60配合长文本即为该效果。Events事件名说明回调参数change值发生变化时触发(val: boolean / string / number) void从 switch.ts 可以看到组件内部实际上声明了三个事件update:model-value、change、input三者都校验参数类型必须为boolean / string / number之一。其中change事件在handleChange中与update:model-value、input一并触发回调参数为切换后的新值即activeValue或inactiveValue。Slots插槽名说明可用版本active-action自定义开启状态下的滑块内容^(2.4.4)inactive-action自定义关闭状态下的滑块内容^(2.4.4)active自定义开启状态下的内容轨道内/外由inline-prompt决定^(2.13.0)inactive自定义关闭状态下的内容^(2.13.0)active/inactive插槽在模板中有两处消费非inline-prompt时渲染在轨道两侧的标签区inline-prompt时渲染在滑块旁的内部区域见 switch.vue因此可以通过这两个插槽在inline-prompt模式下绕过仅首字符限制。Exposes方法名说明类型focus手动聚焦到开关组件() voidfocus()在源码中通过input.value?.focus?.()实现见 switch.vue配合模板中:focus-visible样式见 switch.scss键盘聚焦时滑块外层会出现--el-switch-on-color颜色的描边保证可访问性。此外defineExpose还暴露了只读的checked计算属性可直接通过 ref 判断开关当前是否处于开启状态。无障碍与表单集成从模板结构看switch.vueSwitch 底层是一个不可见的原生input typecheckbox并声明了roleswitch、aria-checked、aria-disabled、aria-label等 ARIA 属性屏幕阅读器可以正确识别其开关语义。键盘上支持 Tab 聚焦与 Enter 键触发切换keydown.enterswitchValue。在表单场景中Switch 通过useFormItem与useFormItemInputId与el-form-item深度集成id 自动关联、禁用/尺寸自动继承、validate-event默认true在每次checked变化时触发formItem.validate(change)因此不需要额外代码即可参与表单校验与 label 关联。小结Element Plus 的 Switch 组件在设计上兼顾了简单与灵活开箱即用默认布尔绑定即可满足绝大多数场景值类型扩展active-value/inactive-value让开关可直接对接业务枚举值状态控制disabled、loading、before-change三层机制保障了异步与受限场景的正确性视觉自定义图标、文字、滑块内容、轨道颜色CSS 变量均可按需定制可访问性底层原生 checkbox 完整 ARIA 语义天然支持键盘操作与屏幕阅读器。结合 switch.ts 与 switch.vue 的源码阅读你不仅能准确使用每一个 API还能理解严格相等判状态、before-change 先行校验、三个事件同时触发等底层约定从而在复杂业务中做出正确的设计决策。【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考