Skip to content

Switch 开关

开关选择组件,支持自定义选中值、自定义文本、自定义颜色、禁用。

组件源码
vue
<script lang="ts" generic="T extends (string | number | boolean)" setup>
import { computed } from 'vue';

const $props = withDefaults(
  defineProps<{
    disabled?: boolean;
    activeValue?: T;
    inactiveValue?: T;
    activeText?: string;
    inactiveText?: string;
    activeColor?: string;
    activeBgColor?: string;
    inactiveColor?: string;
    inactiveBgColor?: string;
    textColor?: string;
  }>(),
  {
    disabled: false,
    activeText: 'YES',
    inactiveText: 'NO',
    activeColor: '#03a9f4',
    activeBgColor: '#ebf7fc',
    inactiveColor: '#f44336',
    inactiveBgColor: '#fcebeb',
    textColor: '#fff'
  }
);

const checked = defineModel<T>('checked', { default: false as T });
const nativeChecked = computed({
  get: () => {
    if ($props.activeValue) {
      return checked.value === $props.activeValue;
    }
    if ($props.inactiveValue) {
      return checked.value !== $props.inactiveValue;
    }
    return !!checked.value;
  },
  set: (value: boolean) => {
    if ($props.disabled) return;

    if (value) {
      checked.value = $props.activeValue ?? (true as T);
      return;
    }
    checked.value = $props.inactiveValue ?? (false as T);
  }
});
</script>

<template>
  <div class="base-switch-button">
    <input
      class="base-switch-checkbox"
      type="checkbox"
      v-model="nativeChecked" />
    <div
      class="knobs"
      :class="disabled ? 'knobs--disabled' : ''"
      :data-text="nativeChecked ? activeText : inactiveText"></div>
    <div class="layer"></div>
  </div>
</template>

<style lang="scss" scoped>
.base-switch-button {
  overflow: hidden;
  position: relative;
  width: 74px;
  height: 36px;
  border-radius: 18px;
  color: v-bind(textColor);

  .base-switch-checkbox {
    position: relative;
    width: 100%;
    height: 100%;
    padding: 0;
    margin: 0;
    opacity: 0;
    cursor: pointer;
    z-index: 3;
  }

  .knobs:before {
    content: attr(data-text);
    position: absolute;
    top: 50%;
    left: 6px;
    transform: translateY(-50%);
    padding: 5px 2px;
    width: 24px;
    height: 24px;
    font-size: 10px;
    text-align: center;
    line-height: 14px;
    background-color: v-bind(inactiveColor);
    border-radius: 15px;
    transition: 0.3s ease all, left 0.3s cubic-bezier(0.18, 0.89, 0.35, 1.15);
  }

  .base-switch-checkbox:checked + .knobs:before {
    content: attr(data-text);
    left: 44px;
    background-color: v-bind(activeColor);
  }

  .base-switch-checkbox:checked ~ .layer {
    background-color: v-bind(activeBgColor);
  }
}

.knobs,
.layer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.knobs {
  z-index: 2;
}

.knobs--disabled {
  z-index: 4;
  cursor: not-allowed;
}

.layer {
  width: 100%;
  background-color: v-bind(inactiveBgColor);
  transition: 0.3s ease all;
  z-index: 1;
}
</style>

基本用法

示例代码
vue
<template>
  <div class="container">
    <div class="flex">
      <label for="" class="mr-10">简单使用:</label>
      <base-switch v-model:checked="checked1" />
    </div>

    <div class="flex">
      <label for="" class="mr-10">指定值:</label>
      <base-switch
        :active-value="1"
        :inactive-value="0"
        v-model:checked="checked2" />
    </div>

    <div class="flex">
      <label for="" class="mr-10">自定义文本:</label>
      <base-switch active-text="开" inactive-text="关" />
    </div>

    <div class="flex">
      <label for="" class="mr-10">自定义颜色:</label>
      <base-switch
        text-color="#000"
        active-color="#67C23A"
        active-bg-color="#f0f9eb"
        inactive-color="#fff"
        inactive-bg-color="#999" />
    </div>
  </div>
</template>

<script lang="ts" setup>
import BaseSwitch from '@/BaseSwitch/BaseSwitch.vue';

import { ref } from 'vue';

const checked1 = ref(false);
const checked2 = ref(1);
</script>

<style lang="scss" scoped>
.container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 20px;
}

.flex {
  display: flex;
  align-items: center;
}

.mr-10 {
  margin-right: 10px;
}
</style>

API

Props

参数名说明类型默认值
checked(v-model)绑定值boolean | number | stringfalse
activeValue选中值boolean | number | string-
inactiveValue未选中值boolean | number | string-
activeText选中文本stringYES
inactiveText未选中文本stringNO
activeColor选中颜色string#03a9f4
activeBgColor选中背景颜色string#ebf7fc
inactiveColor未选中颜色string#f44336
inactiveBgColor未选中背景颜色string#fcebeb
disabled是否禁用booleanfalse
textColor文本颜色string#fff

Events

事件名说明参数
update:checked开关状态切换时触发checked: boolean | number | string

Released under the MIT License.