Element UI el-switch 开关组件详解:用法、参数与实现原理
Element UI el-switch 开关组件详解用法、参数与实现原理【免费下载链接】elementA Vue.js 2.0 UI Toolkit for Web项目地址: https://gitcode.com/gh_mirrors/eleme/elementel-switch是 Element UIA Vue.js 2.0 UI Toolkit中用于在两个相互对立的状态间切换的组件多用于触发开/关语义的功能例如功能开关、付费方式选择、状态启停等。本篇基于官方英文文档 switch.md 的全部内容展开并结合 组件源码、样式实现 与 单元测试完整讲解 Switch 的四种典型用法、全部 Attributes/Events/Methods 参数以及其底层状态管理、表单联动与无障碍a11y设计帮助读者既能直接使用组件也能理解其内部机制以便二次定制。一、组件定位在两个对立状态间切换官方文档对 Switch 的定义只有一句话Switch is used for switching between two opposing states.开关用于在两种相互对立的状态间切换。它的核心交互模型是绑定值通过v-model双向同步接受Boolean/String/Number三种类型点击组件或按回车键触发状态翻转组件内部发出input与change两个事件on/off两种状态可通过背景色、文字描述、图标类名进行差异化呈现。组件入口在 packages/switch/index.js它引入src/component并挂载install方法使组件可以通过Vue.use(Switch)全局注册为el-switch也可按需引入。二、四种典型用法1. 基本用法v-model 与自定义背景色将v-model绑定到一个Boolean类型变量即可active-color与inactive-color属性决定开关在两种状态下的背景色。这是英文文档给出的官方示例el-switch v-modelvalue1 /el-switch el-switch v-modelvalue2 active-color#13ce66 inactive-color#ff4949 /el-switch script export default { data() { return { value1: true, value2: true } } }; /script从源码看颜色并不是通过 CSS 类切换实现的而是在mounted钩子中对.el-switch__core节点直接写入内联样式见 component.vuemounted() { this.coreWidth this.width || 40; if (this.activeColor || this.inactiveColor) { this.setBackgroundColor(); } this.$refs.input.checked this.checked; }其中setBackgroundColor方法会同时设置 core 节点的borderColor与backgroundColorcomponent.vue且每次checked变化时都会被watch重新调用。这意味着不传颜色属性时背景色回退到主题 SCSS 中的默认值——#409EFFon 状态即$--switch-on-color与#C0CCDAoff 状态即$--switch-off-color这正是文档参数表中标注的默认值的实际来源。2. 文字描述active-text / inactive-text使用active-text与inactive-text属性可以分别为on/off状态添加文字描述常用于把开关语义说清楚例如按月付费 / 按年付费el-switch v-modelvalue1 active-textPay by month inactive-textPay by year /el-switch el-switch styledisplay: block v-modelvalue2 active-color#13ce66 inactive-color#ff4949 active-textPay by month inactive-textPay by year /el-switch script export default { data() { return { value1: true, value2: true } } }; /script模板实现上有两个值得注意的细节component.vue左右两个el-switch__label分别通过v-ifinactiveIconClass || inactiveText与v-ifactiveIconClass || activeText控制渲染——没配置文字或图标时对应标签节点根本不存在不会产生多余占位当前状态一侧的文字会加上is-active类并在样式中变为主题色$--color-primary同时通过:aria-hidden把已显示一侧的文字从无障碍树中隐藏避免屏幕阅读器重复朗读。3. 扩展的 value 类型active-value / inactive-valueactive-value与inactive-value可以让开关绑定值摆脱true/false改为任意Boolean、String或Number。官方示例将值扩展为字符串100与0并用el-tooltip展示当前值el-tooltip :contentSwitch value: value placementtop el-switch v-modelvalue active-color#13ce66 inactive-color#ff4949 active-value100 inactive-value0 /el-switch /el-tooltip script export default { data() { return { value: 100 } } }; /script判断是否处于 on 状态的判据是严格相等computed: { checked() { return this.value this.activeValue; } }因此active-value100字符串与绑定值100数字会被判定为不匹配。源码在created钩子中还做了一层自纠正component.vue如果初始value既不是activeValue也不是inactiveValue会立即$emit(input, this.inactiveValue)把绑定值拉回到inactiveValue防止组件进入两个值都不是的中间态。这一点在对接后端返回的任意枚举值如1/0、1/0时尤其重要务必保证类型与字面量一致。4. 禁用状态disabled添加disabled属性即可禁用开关el-switch v-modelvalue1 disabled /el-switch el-switch v-modelvalue2 disabled /el-switch script export default { data() { return { value1: true, value2: false } } }; /script源码中禁用逻辑收敛在一个计算属性switchDisabled中component.vueswitchDisabled() { return this.disabled || (this.elForm || {}).disabled; }即只要父级el-form自身设置了disabled内部所有开关会自动随之禁用——这是通过组件顶部的inject: { elForm: { default: } }注入父级表单实例实现的。点击处理入口switchValue也以此作为第一道闸门switchValue() { !this.switchDisabled this.handleChange(); }单元测试disabled switch should not respond to user clickswitch.spec.js验证了禁用状态下点击 core 区域不会改变绑定值。三、完整 API 参考以下参数表完整继承自官方文档英文文档见 switch.md中文对照版见 switch.md默认值与 component.vue 的 props 定义一一对应。AttributesAttributeDescriptionTypeAccepted ValuesDefaultvalue / v-modelbinding valueboolean / string / number——disabledwhether Switch is disabledboolean—falsewidthwidth of Switchnumber—40active-icon-classclass name of the icon displayed when inonstate, overridesactive-textstring——inactive-icon-classclass name of the icon displayed when inoffstate, overridesinactive-textstring——active-texttext displayed when inonstatestring——inactive-texttext displayed when inoffstatestring——active-valueswitch value when inonstateboolean / string / number—trueinactive-valueswitch value when inoffstateboolean / string / number—falseactive-colorbackground color when inonstatestring—#409EFFinactive-colorbackground color when inoffstatestring—#C0CCDAnameinput name of Switchstring——validate-eventwhether to trigger form validationboolean-true补充说明width控制的是滑块轨道.el-switch__core宽度单位为像素默认 40与mounted中this.coreWidth this.width || 40的兜底一致滑块圆点大小16px、轨道高度20px等由主题变量决定见下文样式部分。active-icon-class/inactive-icon-class与文字属性互斥源码模板中先渲染i :class[activeIconClass]文字span只在!activeIconClass时才出现所以设置图标类名会覆盖文字。name透传到内部隐藏的input typecheckbox上配合id源码额外提供但未列入文档表可用于表单提交与标签关联。validate-event为true时开关状态变化会向上派发el.form.change事件以触发表单校验见下文表单联动一节。EventsEvent NameDescriptionParameterschangetriggers when value changesvalue after changingMethodsMethodDescriptionParametersfocusfocus the Switch component—focus方法并非组件自实现而是来自通用混入 focus.jsElSwitch通过mixins: [Focus(input), ...]注入调用时会把焦点转移到内部refinput的原生 checkbox 上从而兼容键盘操作与无障碍聚焦。四、源码级原理剖析1. 模板结构与无障碍设计根节点是一个带roleswitch的div并同步维护aria-checked与aria-disabledcomponent.vuediv classel-switch :class{ is-disabled: switchDisabled, is-checked: checked } roleswitch :aria-checkedchecked :aria-disabledswitchDisabled click.preventswitchValue input classel-switch__input typecheckbox changehandleChange refinput :idid :namename :true-valueactiveValue :false-valueinactiveValue :disabledswitchDisabled keydown.enterswitchValue 关键设计点真实input typecheckbox被样式置为position: absolute; width: 0; height: 0; opacity: 0switch.scss保留其表单语义与焦点能力视觉呈现全部交给.el-switch__core轨道交互有两条入口div 上的click.preventswitchValue鼠标点击轨道与 input 上的keydown.enterswitchValue键盘回车两条入口最终都汇聚到同一个handleChange:true-value/:false-value与activeValue/inactiveValue保持同步使原生 checkbox 的布尔状态与业务值一一对应。2. 值的变化流程与单一数据源状态翻转的完整链路在handleChange中component.vuehandleChange(event) { const val this.checked ? this.inactiveValue : this.activeValue; this.$emit(input, val); this.$emit(change, val); this.$nextTick(() { // set inputs checked property // in case parent refuses to change components value if (this.$refs.input) { this.$refs.input.checked this.checked; } }); }可以推断出三层设计意图组件不直接修改value而是发出input事件由父组件决定是否更新——value是唯一数据源single source of truth$emit(change, val)的回调参数即变化后的新值与文档 Events 表的描述一致可被 switch.spec.js 中的change event用例验证$nextTick里回写input.checked是为了处理父组件拒绝更新绑定值的场景即使v-model未同步变化内部 checkbox 状态也会被拉回与checked一致。测试用例value is the single source of truthswitch.spec.js专门验证了这一点——只传只读:valuetrue时点击轨道后组件内部checked、is-checked类与 input 的checked属性始终保持一致不会视觉错位。watch中对checked的监听component.vue则负责外部改值时的视图同步绑定值变化后checkbox 状态、背景色与表单校验事件都会随之刷新。sets checkbox value测试用例switch.spec.js验证了vm.value从false改到true时原生 input 的checked能正确联动。3. 表单联动validate-event 与 el-form组件通过inject拿到父级表单elForm并在checked的 watcher 中条件性派发事件if (this.validateEvent) { this.dispatch(ElFormItem, el.form.change, [this.value]); }dispatch来自 emitter.js会沿$parent链向上查找componentName ElFormItem的祖先并$emit(el.form.change, [value])。因此当el-switch置于el-form/el-form-item结构内时状态变化会自动触发所在表单项的change校验若不想让开关参与表单校验例如仅作为展示型开关可将validate-event设为false关闭该行为。4. 从 1.x 迁移属性重命名提示Element UI 2.x 对 1.x 的属性命名做了统一on-*→active-*、off-*→inactive-*。组件通过Migrating混入在控制台中给出告警提示映射关系定义在getMigratingConfig中component.vue1.x 旧属性2.x 新属性on-coloractive-coloroff-colorinactive-coloron-textactive-textoff-textinactive-texton-valueactive-valueoff-valueinactive-valueon-icon-classactive-icon-classoff-icon-classinactive-icon-class从 1.x 代码升级时可按此表逐项替换。五、样式层SCSS 变量与主题定制Switch 的全部视觉尺寸与配色集中在 theme-chalk/src/common/var.scss$--switch-on-color: $--color-primary !default; // on 状态背景色即 #409EFF $--switch-off-color: $--border-color-base !default; // off 状态背景色即 #C0CCDA $--switch-font-size: $--font-size-base !default; // 标签文字字号 $--switch-core-border-radius: 10px !default; // 轨道圆角 $--switch-width: 40px !default; // 轨道宽度与 width 默认值一致 $--switch-height: 20px !default; // 轨道高度 $--switch-button-size: 16px !default; // 白色滑块圆点尺寸switch.scss 中与之对应的渲染逻辑轨道.el-switch__core默认使用$--switch-off-color作为边框色与背景色transition: border-color .3s, background-color .3s提供状态切换动画is-checked状态下轨道切换为$--switch-on-color白色圆点::after伪元素通过left: 100%; margin-left: -($--switch-button-size 1px)滑到右侧is-disabled状态下整体opacity: 0.6且 core 与 label 的cursor变为not-allowed。因此定制主题时修改上述$--switch-*变量即可统一调整全局开关样式而单实例的颜色定制则走active-color/inactive-color内联样式优先级更高。组件的演示页边距样式见 demo-styles/switch.scss。六、TypeScript 类型支持项目内置的类型声明文件 types/switch.d.ts 为ElSwitch提供了完整 prop 类型其中activeValue/inactiveValue声明为string | boolean | number与运行时 props 的[Boolean, String, Number]类型约束一致可直接用于 Vue 2 TypeScript 项目的模板与属性推断。七、单元测试覆盖的行为契约test/unit/specs/switch.spec.js 完整覆盖了组件对外承诺的行为可作为集成使用时的验收清单测试用例验证点createactiveColor/inactiveColor/width初始化时正确落到 core 内联样式rgb(255, 0, 0)、100px文字标签渲染正确switch with iconsinactiveIconClass渲染为i classel-icon-close图标覆盖文字value correctly update点击轨道后背景色与v-model值双向翻转change event点击后change回调收到的是变化后的新值disabled switch should not respond to user click禁用态点击不改变绑定值expand switch valueactive-value100/inactive-value0场景下值在100与0间正确切换value is the single source of truth只读:value场景下内部状态与is-checked类保持同步sets checkbox value外部修改v-model后原生 input 的checked正确联动八、使用建议小结默认场景v-model绑定Boolean变量即可颜色走主题默认值无需额外属性需要业务语义值优先使用active-value/inactive-value如100/0、1/0并注意checked的判定是严格相等类型必须与绑定值完全一致组件在created阶段会自动把非法初始值纠正为inactiveValue需要说明语义短文案用active-text/inactive-text纯图形界面用*-icon-class且两者互斥放在表单中父级el-form disabled会级联禁用内部开关若开关不需要触发校验设置validate-eventfalse需要键盘聚焦通过模板引用调用组件的focus()方法焦点会落在内部隐藏的 checkbox 上。以上用法与原理均以当前仓库Element UIVue 2 版本的实际源码为准涉及版本迁移时请以本仓库对应的 CHANGELOG 与文档为准。【免费下载链接】elementA Vue.js 2.0 UI Toolkit for Web项目地址: https://gitcode.com/gh_mirrors/eleme/element创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →