Switch组件,业务需求中常常遇到。我司的旧项目中,因为没有使用较为成熟点的组件库。本身实现了一个switch组件,可是实现的略微有些丑陋。javascript
https://jsfiddle.net/huang_ju...html
这里,须要实现基础的切换功能和禁用功能。vue
<template id="switch"> <div class="el-switch" @click="handleChange" :class="{'is-checked': value, 'is-disabled': disabled}"> <input type="checkbox" ref="input"> <span class="el-switch__content"> <span class="el-switch__button" :style="{transform}"></span> </span> </div> </template>
let ElSwitch = { name: 'ElSwitch', template: '#switch', props: { value: { type: [Boolean], default: false }, disabled: { type: [Boolean], default: false } }, computed: { transform() { return this.value ? `translate3d(20px, 0, 0)` : ''; } }, methods: { handleChange() { if (!this.disabled) { this.$emit('input', !this.value); this.$nextTick(() => { this.$refs.input.checked = this.value; }); } } }, mounted() { this.$refs.input.checked = this.value; } };
这里须要注意一点,对于自定义的表单组件,Element绑定值到组件中,是用的v-model。而v-model只是一个语法糖,是如下这种的简化形式:java
<input v-model="something"> <input v-bind:value="something" v-on:input="something = $event.target.value">
因此,为了当组件内部值发生改变的时候,能够将变化的值传出来,须要使用这句:ide
this.$emit('input', value);
更具体的,能够参考Vue文档:使用自定义事件的表单输入组件ui
其次,咱们在模板中加了一个 type:checkbox 的input。这不是摆设,当switch组件用在表单中的时候,可能会用到form.name.checked
。因此,咱们须要在值改变的时候,也改变input.chekced属性。这里存在一个时机问题吧,由于v-model绑定了值到组件中,组件中不能直接修改这个值为true来进行改变,须要触发input事件,因此,这里checked的改变须要等到下一次渲染的时候,再进行设置。this
https://jsfiddle.net/huang_ju...spa
自定义activeValue的点在于,有些状况下,switch的值多是0、1.不能肯定就必定是true或者false.net
emm....实现了下,发现也没什么难点,主要关注下改变背景色这一段的代码吧,我以为写着仍是挺好的插件
let ElSwitch = { name: 'ElSwitch', template: '#switch', props: { // ... }, computed: { checked() { return this.value === this.activeValue; }, // ... }, methods: { handleChange() { //... }, setBackgroundColor() { let newColor = this.checked ? this.activeColor : this.inactiveColor; this.$refs.content.style.borderColor = newColor; this.$refs.content.style.backgroundColor = newColor; } }, watch: { checked() { this.$refs.input.checked = this.value; if (this.activeColor || this.inactiveColor) { this.setBackgroundColor(); } } }, created() { if (!~[this.activeValue, this.inactiveValue].indexOf(this.value)) { this.$emit('input', this.inactiveValue); } }, mounted() { this.$refs.input.checked = this.checked; if (this.activeColor || this.inactiveColor) { this.setBackgroundColor(); } } };
改变背景颜色,是发生在this.$emit('input',value)
以后的,这有一个执行顺序的问题。若是在this.$nextTick中进行改变背景色也行,效果同样,只是handleChange的代码长一点。但这里经过监听computed属性(checked),来作响应式改变,代码,emm....,感受是更加清晰了点吧。
Switch插件的编写不是很难,能够关注两点: