el-switch 源码解析

268 阅读1分钟

el-switch 源码解析

基本用法

<template>
  <el-switch
    v-model="value"
    active-color="#13ce66"
    inactive-color="#ff4949"
  >
  </el-switch>
</template>

<script>
export default {
  data() {
    return {
      value: true
    }
  }
};
</script>

el-switch 的dom基本结构如下,可以看到switch实际上是一个checkbox

PixPin_2024-02-14_16-34-59.png

在vue中checkbox有两个属性true-value和false-value,表示选中和未选中时组件的toggle值

PixPin_2024-02-14_16-52-52.png

在组件源码中使用value和true-value(activeValue),来表示组件是否选中

<input :true-value="activeValue" />
// computed checked
checked() {
  return this.value === this.activeValue;
},

点击切换时,触发了change事件

handleChange(event) {
    // 如果是checked 则val为false 否则val为true
    const val = this.checked ? this.inactiveValue : this.activeValue;
    // 因为是绑定了v-model,所以要触发input事件
    this.$emit('input', val);
    // 触发change事件
    this.$emit('change', val);
    this.$nextTick(() => {
      // set input's checked property
      // in case parent refuses to change component's value
      if (this.$refs.input) {
        this.$refs.input.checked = this.checked;
      }
    });
 }

监听checked属性,发生变化时重新设置背景颜色

watch: {
  checked() {
    this.$refs.input.checked = this.checked;
    if (this.activeColor || this.inactiveColor) {
      this.setBackgroundColor();
    }
    if (this.validateEvent) {
      this.dispatch('ElFormItem', 'el.form.change', [this.value]);
    }
  }
},
setBackgroundColor() {
  let newColor = this.checked ? this.activeColor : this.inactiveColor;
  this.$refs.core.style.borderColor = newColor;
  this.$refs.core.style.backgroundColor = newColor;
}

文字描述

当设置了active-text 、inactive-text时,实际上就是在组件两端增加了一个span元素,当选中或非选中时

动态设置is-acitve class,改变字体颜色

如果设置了图标类名 activeIconClass inactiveIconClass 会忽略text

PixPin_2024-02-14_17-27-26.png

禁用状态

设置了disabled属性,动态设置 is-diabled class

validate-event

如果设置了这个属性为true会在切换时触发form的校验

if (this.validateEvent) {
  this.dispatch('ElFormItem', 'el.form.change', [this.value]);
}

示例代码

<template>
 <div>
   <el-form :model="formModel" :rules="rules" ref="form">
     <el-form-item prop="switch" label="开关">
       <el-switch
         v-model="formModel.switch"
         active-text="按月付费"
         inactive-text="按年付费"
         :validate-event="false"
       />
     </el-form-item>
   </el-form>
   <el-button type="primary" @click="handleSubmit">提交</el-button>
 </div>
</template>

<script>
export default {
  data() {
    return {
      formModel: {
        switch: true
      },
      rules: {
        switch: [{ validator: this.validateSwitch, trigger: 'change' }]
      }
    }
  },
  methods: {
    handleSubmit() {
      console.log(this.$refs.form);
      this.$refs.form.validate().then(res => {
        console.log(res);
      })
    },
    validateSwitch(rule, value, callback) {
      console.log(value);
      if(value) {
        callback(new Error('can not be true'))
      }else {
        callback()
      }
    }
  }
};
</script>