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插件的編寫不是很難,能夠關注兩點: