51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Vue实现switch开关组件

# Switch开关实现功能 {#switch开关实现功能}

开关组件,支持自定义宽度、开关颜色和开关值。

# 演示 {#演示}

开关

开关--默认

开关状态:false

开关--禁用

开关状态:false

开关--修改颜色(支持渐变色)

开关状态:true

开关--修改状态默认值

开关状态:open

开关--改变宽度

开关状态:false

开关--prevent default

开关状态:false

# 基础用法 {#基础用法}

<oc-switch v-model="switchValue"></oc-switch>

<oc-switch
  v-model="switchValue"
  activeValue="open"
  inactiveValue="close"
  activeColor="#2b88e3"
  inactiveColor="#f5f5f5"
  :width="54"
  :disabled="false"
  :preventDefault="true"
  @onClick="switchClick"
  @onChange="switchChange"
></oc-switch>

# 配置参数 {#配置参数}

| 参数 | 说明 | 类型 | 可选值 | 默认值 | |-----------------|-----------------------|---------------------------|-----|---------| | value / v-model | 绑定值 | Boolean / String / Number | - | false | | disabled | 是否禁用 | Boolean | - | false | | width | 开关宽度,单位 px | Number | - | 44 | | activeValue | switch 打开时的值 | Boolean / String / Number | - | true | | inactiveValue | switch 关闭时的值 | Boolean / String / Number | - | false | | activeColor | switch 打开时的背景色(支持渐变色) | String | - | #ff5040 | | inactiveColor | switch 关闭时的背景色(支持渐变色) | String | - | #d9d9d9 | | preventDefault | 阻止默认点击事件(用于异步切换开关状态) | Boolean | - | - |

# 模版调用的回调方法 {#模版调用的回调方法}

| 方法名 | 说明 | 回调参数 | |----------|---------------------|-------| | onClick | switch 点击时的回调函数 | 点击时的值 | | onChange | switch 状态发生变化时的回调函数 | 新状态的值 |

# 源码 {#源码}

点击查看 OcSwiper.vue 组件源码

<template>
  <span
    :class="[
      'oc-switch',
      { 'oc-switch-disabled': disabled },
      checked ? 'oc-switch-active' : 'oc-switch-inactive',
    ]"
    :style="styleObject"
    @click.prevent="clickHandler"
    ref="switch"
  ></span>
</template>
<script>
export default {
  name: "OcSwitch",
  props: {
    value: {
      type: [Boolean, String, Number],
      default: false,
    },
    disabled: {
      // 是否禁用
      type: Boolean,
      default: false,
    },
    activeValue: {
      // switch 打开时的值
      type: [Boolean, String, Number],
      default: true,
    },
    inactiveValue: {
      // switch 关闭时的值
      type: [Boolean, String, Number],
      default: false,
    },
    activeColor: {
      // switch 打开时的背景色(支持渐变色)
      type: String,
      default: "",
    },
    inactiveColor: {
      // switch 关闭时的背景色(支持渐变色)
      type: String,
      default: "",
    },
    width: {
      // 开关宽度,单位px
      type: Number,
    },
    preventDefault: {
      // 阻止默认点击事件(用于异步切换开关状态)
      type: Boolean,
    },
  },
  created() {
    // 若缺省值不在可选范围内,则默认为关。
    if ([this.activeValue, this.inactiveValue].indexOf(this.value) === -1) {
      this.$emit("input", this.inactiveValue);
    }
  },
  computed: {
    checked() {
      return this.value === this.activeValue;
    },
    styleObject() {
      let styleObject = {};
      // 自定义背景色
      if (this.activeColor || this.inactiveColor) {
        let newColor = this.checked ? this.activeColor : this.inactiveColor;
        styleObject.background = newColor;
      }
      // 自定义宽度
      if (this.width) {
        styleObject.width = this.width + "px";
      }
      return styleObject;
    },
  },
  methods: {
    clickHandler() {
      if (this.disabled) return;
      if (this.preventDefault) {
        this.$emit("onClick", this.value);
      } else {
        this.changeValue();
      }
    },
    changeValue() {
      const val = this.checked ? this.inactiveValue : this.activeValue;
      this.$emit("input", val); // 更新父组件值
      this.$emit("onChange", val); // 开关状态改变事件
    },
  },
};
</script>
<style lang="scss" scoped>
$oc-switch-transition-duration: 300ms !default; // switch切换动画时长
$oc-switch-bg-color-active: #ff5040 !default;
$oc-switch-bg-color-inactive: #d9d9d9 !default;
.oc-switch {
  display: inline-block;
  position: relative;
  overflow: hidden;
  width: 44px;
  height: 24px;
  border-radius: 12px;
  transition: all $oc-switch-transition-duration;
  cursor: pointer;
  box-sizing: border-box;
  & * {
    box-sizing: inherit;
  }
  &::before,
  &::after {
    box-sizing: inherit;
  }
  &.oc-switch-disabled {
    opacity: 0.6;
    cursor: not-allowed;
  }
  &::after {
    content: "";
    position: absolute;
    top: 2px;
    background-color: #fff;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    transition: all $oc-switch-transition-duration;
  }
  &-active {
    background: $oc-switch-bg-color-active;
    &::after {
      left: 100%;
      margin-left: -22px;
    }
  }
  &-inactive {
    background: $oc-switch-bg-color-inactive;
    &::after {
      left: 2px;
    }
  }
}
</style>

点击查看 DEMO 源码

<template>
  <div class="demo-switch-page">
    <h1>开关</h1>
    <section class="demo">
      <h2>开关--默认</h2>
      <oc-switch v-model="switchValue1" @onChange="switchChange"></oc-switch>
      <div class="ret">开关状态:{{ switchValue1 }}</div>
    </section>
    <section class="demo">
      <h2>开关--禁用</h2>
      <oc-switch v-model="switchValue1" :disabled="true"></oc-switch>
      <oc-switch
        v-model="switchValue1"
        activeColor="#409eff"
        inactiveColor="#dcdfe6"
        :disabled="true"
      ></oc-switch>
      <oc-switch
        v-model="switchValue1"
        activeColor="#13ce66"
        inactiveColor="#ff4949"
        :disabled="true"
      ></oc-switch>
      <oc-switch
        v-model="switchValue1"
        activeColor="#2b88e3"
        inactiveColor="#f5f5f5"
        :disabled="true"
      ></oc-switch>
      <div class="ret">开关状态:{{ switchValue1 }}</div>
    </section>
    <section class="demo">
      <h2>开关--修改颜色(支持渐变色)</h2>
      <oc-switch
        v-model="switchValue2"
        activeColor="#409eff"
        inactiveColor="#dcdfe6"
      ></oc-switch>
      <oc-switch
        v-model="switchValue2"
        activeColor="#13ce66"
        inactiveColor="#ff4949"
      ></oc-switch>
      <oc-switch
        v-model="switchValue2"
        activeColor="#2b88e3"
        inactiveColor="#f5f5f5"
      ></oc-switch>
      <oc-switch
        v-model="switchValue2"
        activeColor="linear-gradient(to left, #ff6c49 0%, #ff9a3d 100%)"
        inactiveColor="linear-gradient(180deg, #ffe666, #fc3)"
      ></oc-switch>
      <div class="ret">开关状态:{{ switchValue2 }}</div>
    </section>
    <section class="demo">
      <h2>开关--修改状态默认值</h2>
      <oc-switch
        v-model="switchValue3"
        activeValue="open"
        inactiveValue="close"
      ></oc-switch>
      <div class="ret">开关状态:{{ switchValue3 }}</div>
    </section>
    <section class="demo">
      <h2>开关--改变宽度</h2>
      <oc-switch v-model="switchValue4" activeValue="a" :width="40"></oc-switch>
      <oc-switch v-model="switchValue4" activeValue="a" :width="54"></oc-switch>
      <div class="ret">开关状态:{{ switchValue4 }}</div>
    </section>
    <section class="demo">
      <h2>开关--prevent default</h2>
      <oc-switch
        v-model="switchValue5"
        :preventDefault="true"
        @onClick="switchClick"
      ></oc-switch>
      <div class="ret">开关状态:{{ switchValue5 }}</div>
    </section>
  </div>
</template>

<script>
export default {
  name: "DemoSwitch",
  data() {
    return {
      switchValue1: false,
      switchValue2: true,
      switchValue3: "open",
      switchValue4: false,
      switchValue5: false,
    };
  },
  methods: {
    switchChange(msg) {
      console.log("switch change:", msg);
    },
    switchClick(val) {
      alert("你点击了开关");
      this.switchValue5 = !val;
    },
  },
};
</script>

<style lang="scss" scoped>
.demo-switch-page {
  margin: 10px;
}

.demo {
  margin-top: 15px;
  margin-left: 5px;
}

h1 {
  margin-bottom: 12px;
  font-size: 20px;
  color: #ff5040;
}

h2 {
  font-size: 18px;
  color: #ff00ff;
}

.ret {
  margin-top: 10px;
  color: 14px;
}

ul {
  margin-left: 5px;
  width: 150px;
}

li {
  margin-top: 5px;
}

.slot-icon {
  font-size: 24px;
  color: #aaa;
}

.slot-text {
  text-align: left;
  color: 14px;
}
.oc-switch {
  margin-right: 20px;
}
</style>
赞(5)
未经允许不得转载:工具盒子 » Vue实现switch开关组件