3.23 Switch 开关
简介
开关选择器 Switch 用于表示开关状态/两种状态之间的切换时。本文将分析源码实现,耐心读完,相信会对您有所帮助。组件源码实现详见packages/switch/src/component.vue 。 🔗 组件文档 Switch 🔗 gitee源码 component.vue
组件checkbox单独使用可以表示两种状态之间的切换,和 switch 类似。两者在于切换 switch 会直接触发状态改变,而 checkbox 一般用于状态标记,需要和提交操作配合。
更多组件剖析详见 👉 📚 Element 2 源码剖析组件总览 。
源码实现
组件的 prop 声明,各属性功能说明详见 官方文档switch#attributes 。
组件的根节点是类名el-switch的div元素,内部有四个子元素:
type="checkbox"的input 元素。关闭时的图标/文字描述(左侧),类名
el-switch__label--left的span 元素。组件核心,类名
el-switch__core的span 元素。打开时的图标/文字描述(右侧),类名
el-switch__label--right的span 元素。
<template>
<div
class="el-switch"
:class="{ 'is-disabled': switchDisabled, 'is-checked': checked }"
role="switch"
:aria-checked="checked"
:aria-disabled="switchDisabled"
@click.prevent="switchValue"
>
<input class="el-switch__input" type="checkbox">
<span :class="['el-switch__label', 'el-switch__label--left']"></span>
<span class="el-switch__core" ref="core" ></span>
<span :class="['el-switch__label', 'el-switch__label--right']"></span>
</div>
</template>组件页面渲染内容如下。
页面无法看到 input 元素,由其样式.el-switch__input可知宽/高/透明度都为0。页面无法聚焦到该元素。
根节点
根据组件的禁用状态以及打开状态绑定样式 is-disabled、is-checked。
计算属性checked判定组件是否打开状态。组件扩展的 value 类型,不仅支持boolean类型,也支持string/number。当使用string/number类型参数时, 需要手动设定activeValue 和 inactiveValue属性值。
计算属性switchDisabled返回组件是否禁用。
添加点击事件@click="switchValue",用于实现组件点击后切换状态(当设置文字描述时,点击文字也能实现状态切换)。事件使用了修饰符 prevent,当触发的事件调用 event.preventDefault(),阻止自身默认事件的执行。
方法 switchValue 在非禁用状态下调用handleChange方法,实现开关状态的切换。
方法 handleChange中使用this.$emit('input', val);更新组件v-model值也就是value值。没有看到更新属性value值的操作。使用this.$emit('change', val);触发自定义状态变化事件。
组件使用v-model,需要使用
$emit('input')来改变组件v-model值,否则无法更新用户传入的v-model值。 因为
属性 role 、aria-checked 、aria-disabled用于实现 ARIA无障碍网页应用。
状态描述
组件支持使用文字或者icon图标对状态进行描述。
组件左侧为关闭状态描述元素,只有设置了属性inactiveIconClass或inactiveText才会显示。若设置属性inactiveIconClass会忽略 inactiveText。
组件右侧为打开状态描述元素,实现逻辑请参考左侧分析。
组件核心
span元素是开关的外层容器,圆形滑块是由:after伪元素实现。
通过CSS设置高度、外边框圆角实现左右半圆效果。
定义打开状态下开关背景色。
圆形滑块使用绝对定位,使用 left和margin-left定义打开状态下滑块位置(最右侧) 。 使用transition: all .3s定义了滑块动画时间以及背景颜色变化的时间。
属性 coreWidth 默认值为40。若设置了不同状态的开关背景色,在mounted中会调用方法setBackgroundColor。将元素样式border-color、 background-color更新为当前状态设置的颜色。
input 元素
关于 input 元素的功能和使用场景无法准确分析推测。
文档中组件暴露出的 fous方法就是用于获取input元素的焦点 this.$refs["input"].focus()。
将相关代码移除,组件也可正常运行。此处逻辑不做过多赘述!
拾遗
在created中,进行了数值处理,若是v-model的值不是 activeValue inactiveValue任意属性值,使用$emit('input',val) 更新v-model值为inactiveValue ,让组件置位关闭状态。!和~运算符让number转变成boolen类型。
当设置属性 validateEvent值为true 时,改变 switch 状态时是否触发表单的校验,触发组件 formItem 的方法 onFieldChange。具体校验逻辑等到组件Form 分析文章详细介绍。
组件样式
组件样式源码 packages\theme-chalk\src\switch.scss 使用混合指令 b、e、when、m 嵌套生成组件样式。
最后更新于