Switch組件

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

自定義activeValue、背景色、寬度

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

  • 經過watch監聽computed屬性,做爲初學者,這點之後能夠關注一下
  • 多巧用ref,獲取節點、設置屬性很方便
相關文章
相關標籤/搜索