Element(Vue 2.0)Switch 开关组件完全指南:从基础用法到源码级实现
2026/9/19 7:45:27 网站建设 项目流程

Element(Vue 2.0)Switch 开关组件完全指南:从基础用法到源码级实现

【免费下载链接】elementA Vue.js 2.0 UI Toolkit for Web项目地址: https://gitcode.com/gh_mirrors/eleme/element

Element 是饿了么团队开源的 Vue.js 2.0 UI 组件库(仓库路径gh_mirrors/eleme/element),其中 Switch 开关组件用于在两个相互对立的状态(如「开/关」「按月/按年」)之间进行切换。本文以仓库中的官方文档(examples/docs/es/switch.md,同内容还提供 中文版 与 英文版)为核心骨架,结合组件源码、单元测试与主题样式,系统讲解el-switch的完整用法、全部属性/事件/方法与底层实现原理,帮助你既能在业务中熟练使用,也能深入理解其运行机制。

一、组件定位与适用场景

Switch 的本质是一个「二选一」的状态切换控件,常用于触发「开/关」等互斥操作。与 Checkbox 相比,Switch 更强调即时生效的动作语义(如开关某功能、切换计费方式),视觉上是一个可滑动的滑块。

在 Element 中,Switch 是一个独立的可安装组件,注册方式与其他组件一致,位于 packages/switch/index.js:

import Switch from './src/component'; Switch.install = function(Vue) { Vue.component(Switch.name, Switch); }; export default Switch;

在模板中即可直接使用:

<el-switch v-model="value"></el-switch>

二、基本用法:v-model 绑定与背景色定制

Switch 通过v-model绑定一个Boolean类型的变量,开启/关闭状态会自动同步回数据。默认开启状态为true、关闭状态为false

官方文档(examples/docs/es/switch.md)给出的基本示例如下:

<el-switch v-model="value1"> </el-switch> <el-switch v-model="value2" active-color="#13ce66" inactive-color="#ff4949"> </el-switch> <script> export default { data() { return { value1: true, value2: true } } }; </script>

其中:

  • v-model完成值的双向绑定;
  • active-color指定「打开」状态的背景色(默认为主题色#409EFF);
  • inactive-color指定「关闭」状态的背景色(默认为#C0CCDA)。

源码验证:颜色是如何生效的

在组件源码 packages/switch/src/component.vue 中,背景色通过setBackgroundColor方法写入内部核心滑块(.el-switch__core)的样式:

setBackgroundColor() { let newColor = this.checked ? this.activeColor : this.inactiveColor; this.$refs.core.style.borderColor = newColor; this.$refs.core.style.backgroundColor = newColor; }

该方法在mounted时首次执行(前提是设置了activeColorinactiveColor),并在checked状态变化的watch回调中再次执行,从而实现开/关切换时颜色的同步刷新。对应的单元测试(test/unit/specs/switch.spec.js)验证了activeColor="#0f0"inactiveColor="#f00"时,核心元素的backgroundColor会随点击在绿/红之间正确切换。

三、文字描述:active-text 与 inactive-text

若希望开关两侧显示文字(如「按月付费 / 按年付费」),可使用active-textinactive-text属性:

<el-switch v-model="value1" active-text="Pay by month" inactive-text="Pay by year"> </el-switch> <el-switch style="display: block" v-model="value2" active-color="#13ce66" inactive-color="#ff4949" active-text="Pay by month" inactive-text="Pay by year"> </el-switch> <script> export default { data() { return { value1: true, value2: true } } }; </script>

从模板结构看文字渲染逻辑

在源码模板(packages/switch/src/component.vue)中,文字与图标被渲染为左右两个label区域:

<span :class="['el-switch__label', 'el-switch__label--left', !checked ? 'is-active' : '']" v-if="inactiveIconClass || inactiveText"> <i :class="[inactiveIconClass]" v-if="inactiveIconClass"></i> <span v-if="!inactiveIconClass && inactiveText" :aria-hidden="checked">{{ inactiveText }}</span> </span> <span class="el-switch__core" ref="core" :style="{ 'width': coreWidth + 'px' }"></span> <span :class="['el-switch__label', 'el-switch__label--right', checked ? 'is-active' : '']" v-if="activeIconClass || activeText"> <i :class="[activeIconClass]" v-if="activeIconClass"></i> <span v-if="!activeIconClass && activeText" :aria-hidden="!checked">{{ activeText }}</span> </span>

关键细节:

  • 关闭态文字(inactive-text)显示在左侧(label--left),打开态文字(active-text)显示在右侧(label--right);
  • 通过is-active类标记当前生效的文字,样式中生效侧文字使用主题色高亮(见 packages/theme-chalk/src/switch.scss);
  • 当设置了active-icon-class/inactive-icon-class图标类时,优先渲染图标而忽略文字,两者互斥。

主题变量与尺寸

Switch 的尺寸与配色由主题变量控制,定义于 packages/theme-chalk/src/common/var.scss:

$--switch-on-color: $--color-primary !default; $--switch-off-color: $--border-color-base !default; $--switch-font-size: $--font-size-base !default; $--switch-core-border-radius: 10px !default; $--switch-width: 40px !default; $--switch-height: 20px !default; $--switch-button-size: 16px !default;

滑块(.el-switch__core)的宽度通过内联样式:style="{ 'width': coreWidth + 'px' }"设置为width属性的值(默认 40px),高度固定 20px,圆形按钮直径 16px,滑块位移与颜色变化带有 0.3s 的过渡动画。源码中变量注释也指出:宽度在代码中写死为 40px 初始值,因此$--switch-width等变量实际意义有限,主题定制以width属性为主。

四、扩展 value 类型:active-value 与 inactive-value

默认情况下 Switch 的绑定值为Boolean。若业务需要,可设置active-valueinactive-value属性,二者接受BooleanStringNumber类型的值,使开关直接表达业务语义(如字符串'100''0')。

官方文档示例(结合 Tooltip 展示当前值):

<el-tooltip :content="'Switch value: ' + value" placement="top"> <el-switch v-model="value" active-color="#13ce66" inactive-color="#ff4949" active-value="100" inactive-value="0"> </el-switch> </el-tooltip> <script> export default { data() { return { value: '100' } } }; </script>

源码验证:值切换与初始化矫正

组件内部通过checked计算属性判断当前是否处于「打开」状态:

computed: { checked() { return this.value === this.activeValue; }, ... }

注意这里使用严格相等===),因此active-value的类型必须与绑定值严格一致(例如都传字符串'100',而非字符串与数字混用)。

点击滑块时,handleChange依据当前状态切换到另一侧的值:

handleChange(event) { const val = this.checked ? this.inactiveValue : this.activeValue; this.$emit('input', val); this.$emit('change', val); ... }

此外,created钩子会做一次初始化矫正:若初始绑定的value既不是activeValue也不是inactiveValue,则强制将值修正为inactiveValue

created() { if (!~[this.activeValue, this.inactiveValue].indexOf(this.value)) { this.$emit('input', this.inactiveValue); } }

对应的单元测试(expand switch value)验证了绑定'100'/'0'时,点击后值在'100''0'之间往返切换。

五、禁用状态:disabled

设置disabled属性后,Switch 进入禁用态,不再响应用户点击:

<el-switch v-model="value1" disabled> </el-switch> <el-switch v-model="value2" disabled> </el-switch> <script> export default { data() { return { value1: true, value2: false } } }; </script>

源码验证:禁用是如何实现的

  • 组件根节点在禁用时添加is-disabled类(CSS 中表现为滑块与文字区域cursor: not-allowed、整体opacity: 0.6);
  • switchDisabled计算属性同时考虑自身disabled与所在表单(elForm)的禁用状态,即外层el-form设置disabled时,内部 Switch 也会自动禁用:
computed: { switchDisabled() { return this.disabled || (this.elForm || {}).disabled; } }
  • 点击事件入口switchValue会做守卫判断:!this.switchDisabled && this.handleChange()
  • 内部隐藏的<input type="checkbox">也会同步:disabled="switchDisabled"

测试用例disabled switch should not respond to user click专门验证了禁用后点击滑块,绑定值保持不变。

六、完整的 Attributes / Events / Methods API

官方文档(examples/docs/es/switch.md)列出了完整的 API 表格,以下结合源码逐一补充默认值与类型约束。

Attributes

参数说明类型可选值默认值
value / v-model绑定值boolean / string / number
disabled是否禁用booleanfalse
widthswitch 的宽度(像素)number40
active-icon-classswitch 打开时所显示图标的类名,设置此项会忽略active-textstring
inactive-icon-classswitch 关闭时所显示图标的类名,设置此项会忽略inactive-textstring
active-textswitch 打开时的文字描述string
inactive-textswitch 关闭时的文字描述string
active-valueswitch 打开时的值boolean / string / numbertrue
inactive-valueswitch 关闭时的值boolean / string / numberfalse
active-colorswitch 打开时的背景色string#409EFF
inactive-colorswitch 关闭时的背景色string#C0CCDA
nameswitch 对应的 name 属性string
validate-event改变 switch 状态时是否触发表单的校验booleantrue

源码补充:在 packages/switch/src/component.vue 中,name会透传到内部隐藏的<input>元素(<input ... :name="name">),因此 Switch 的值可以随表单提交;validate-eventtrue时,状态变化会通过dispatch('ElFormItem', 'el.form.change', [this.value])触发所在表单项的校验(组件混入了 src/mixins/emitter.js 的dispatch方法)。此外源码还额外支持文档表格之外的id属性(透传给内部 input)。对应的 TypeScript 类型声明见 types/switch.d.ts。

Events

事件名称说明回调参数
changeswitch 状态发生变化时的回调函数新状态的值

change事件在handleChange中与input事件同时触发:this.$emit('input', val); this.$emit('change', val);。测试用例change event验证了点击滑块后回调能收到新的状态值。

Methods

方法名说明参数
focus使 Switch 获取焦点

focus方法来自Focus('input')混入(见 src/mixins/focus.js),调用后会将焦点移到组件内部隐藏的<input>元素上,便于无障碍键盘操作(组件根节点声明了role="switch"aria-checkedaria-disabled,并支持 Enter 键切换)。

七、无障碍与键盘交互细节

从模板可以看出,Switch 并非简单使用原生 checkbox 外观,而是「隐藏 input + 自绘滑块」的结构:

  • 原生<input type="checkbox">宽高为 0、完全透明(见 packages/theme-chalk/src/switch.scss 中.el-switch__input的样式),但保留namedisabledchecked等语义属性;
  • 根节点使用role="switch"并维护aria-checked/aria-disabled
  • 键盘聚焦 input 后按 Enter 键(@keydown.enter="switchValue")即可切换状态。

八、数据流与「单一数据源」原则

Switch 遵循 Vue 单向数据流 +v-model约定:用户操作只负责发出input事件,最终展示状态永远以父组件的value为准。这一点在源码中有两处体现:

  1. handleChange$nextTick中重新将内部 input 的checked同步为this.checked,注释说明这是为了「防止父组件拒绝修改组件值」:
this.$nextTick(() => { if (this.$refs.input) { this.$refs.input.checked = this.checked; } });
  1. checkedwatch回调同样会在值变化时同步 input 的checked与背景色。

测试用例value is the single source of truth专门验证:当父组件只传入:value="true"而不监听更新时,无论点击多少次,组件都保持选中态(is-checked类与 input.checked 均保持true);sets checkbox value则验证了外部修改v-model值会正确反映到内部 input 的checked状态。

九、图标开关与迁移兼容

Switch 支持在滑块两侧显示图标(如打勾el-icon-check与关闭el-icon-close):

<el-switch v-model="value" active-icon-class="el-icon-check" inactive-icon-class="el-icon-close"> </el-switch>

设置图标类后,对应侧的文字描述会被忽略(模板中v-if="inactiveIconClass || inactiveText"与内部互斥判断)。测试用例switch with icons验证了.el-switch__label--left下会渲染包含el-icon-close类的<i>元素。

另外,组件通过getMigratingConfig(混入 src/mixins/migrating.js)在开发环境下提示旧版本属性改名:on-coloractive-coloroff-colorinactive-coloron-textactive-textoff-textinactive-texton-valueactive-valueoff-valueinactive-valueon-icon-classactive-icon-classoff-icon-classinactive-icon-class。从旧版迁移到新版时按此对照表更新属性名即可。

十、样式定制建议

Switch 的视觉样式集中在 packages/theme-chalk/src/switch.scss,主题变量集中在 packages/theme-chalk/src/common/var.scss 的/* Switch */区块。主要定制点:

  • 颜色:运行时通过active-color/inactive-color属性覆盖;主题层面可覆盖$--switch-on-color$--switch-off-color
  • 尺寸:通过width属性(number,单位 px)控制总宽度,高度与按钮直径由主题变量$--switch-height$--switch-button-size控制;
  • 圆角与过渡$--switch-core-border-radius控制滑块圆角,.el-switch__core上定义了border-color .3s, background-color .3s的颜色过渡与.3s的按钮位移过渡。

结语

Element 的 Switch 组件虽然 API 简洁,但内部实现涵盖了 v-model 双向绑定、严格相等状态判断、值初始化矫正、表单联动校验、表单级禁用继承、无障碍键盘支持以及主题变量定制等多层设计。通过本文的「文档 + 源码 + 测试」三重对照,你可以在 examples/docs/es/switch.md、packages/switch/src/component.vue 与 test/unit/specs/switch.spec.js 之间自由穿梭,既快速上手,也能在需要深度定制时有的放矢。

【免费下载链接】elementA Vue.js 2.0 UI Toolkit for Web项目地址: https://gitcode.com/gh_mirrors/eleme/element

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询