Vue3开关(Switch)

70 篇文章 4 订阅
68 篇文章 3 订阅

Vue2开关(Switch)

可自定义设置以下属性:

  • 选中时的内容(onInfo),类型:string,默认 ''

  • 未选中时的内容(offInfo),类型:string,默认 ''

  • 是否禁用(disabled),类型:boolean,默认 false

  • 指定当前是否选中(v-model:checked),类型:boolean,默认 false

  • 节点样式(nodeStyle),类型:CSSProperties,默认 {}

效果如下图:在线预览

①创建开关组件Switch.vue:

<script setup lang="ts">
import type { CSSProperties } from 'vue'
interface Props {
  onInfo?: string // 选中时的内容
  offInfo?: string // 未选中时的内容
  disabled?: boolean // 是否禁用
  checked?: boolean // (v-model)指定当前是否选中
  nodeStyle?: CSSProperties // 节点样式
}
const props = withDefaults(defineProps<Props>(), {
  onInfo: '',
  offInfo: '',
  disabled: false,
  checked: false,
  nodeStyle: () => ({})
})
const emit = defineEmits(['update:checked', 'change'])
function onSwitch () {
  emit('update:checked', !props.checked)
  emit('change', !props.checked)
}
</script>
<template>
  <div class="m-switch-wrap">
    <div @click="disabled ? () => false : onSwitch()" :class="['m-switch', { 'switch-checked': checked, 'disabled': disabled }]">
      <div :class="['u-switch-inner', checked ? 'inner-checked' : 'inner-unchecked' ]">{{ checked ? onInfo : offInfo }}</div>
      <div :class="['u-node', { 'node-checked': checked }]" :style="nodeStyle">
        <slot name="node"></slot>
      </div>
    </div>
  </div>
</template>
<style lang="less" scoped>
.m-switch-wrap {
  display: inline-block;
  height: 22px;
  min-width: 44px;
  .m-switch {
    position: relative;
    display: inline-flex;
    align-items: center;
    vertical-align: top;
    width: 100%;
    height: 100%;
    color: rgba(0, 0, 0, .88);
    font-size: 14px;
    line-height: 22px;
    background: rgba(0, 0, 0, .25);
    border-radius: 100px;
    cursor: pointer;
    transition: all .2s;
    &:hover:not(.disabled) {
      background: rgba(0, 0, 0, .45);
    }
    .u-switch-inner {
      color: #fff;
      font-size: 14px;
      line-height: 22px;
      padding: 0 8px;
      transition: all .2s ease-in-out;
    }
    .inner-checked {
      margin-right: 18px;
    }
    .inner-unchecked {
      margin-left: 18px;
    }
    .u-node {
      position: absolute;
      left: 2px;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 18px;
      height: 18px;
      background: #FFF;
      border-radius: 100%;
      cursor: pointer;
      transition: all .2s ease-in-out;
    }
    .node-checked { // 结果等价于right: 2px; 为了滑动效果都以左边为基准进行偏移
      left: 100%;
      margin-left: -2px;
      transform: translateX(-100%);
    }
  }
  .switch-checked {
    background: @themeColor;
    &:hover:not(.disabled) {
      background: #4096ff;
    }
  }
  .disabled {
    cursor: not-allowed;
    opacity: .65;
    .u-node {
      cursor: not-allowed;
    }
  }
}
</style>

 ②在要使用的页面引入:

<script setup lang="ts">
import Switch from './Switch.vue'
import { ref, watchEffect } from 'vue'

const checked = ref(true)
function onChange(checked: boolean) {
  console.log('checked:', checked)
}
watchEffect(() => {
  console.log('checked:', checked.value)
})
</script>
<template>
  <div>
    <h1>{{ $route.name }} {{ $route.meta.title }}</h1>
    <h2 class="mt30 mb10">基本使用</h2>
    <Switch v-model:checked="checked" @change="onChange" />
    <h2 class="mt30 mb10">禁用开关</h2>
    <Switch v-model:checked="checked" disabled />
    <h2 class="mt30 mb10">带文字的开关</h2>
    <Switch v-model:checked="checked" onInfo="开" offInfo="关" />
    <h2 class="mt30 mb10">自定义图标和样式</h2>
    <Switch class="u-theme-switch" v-model:checked="checked" :node-style="{ background: checked ? '#001529' : '#fff' }">
      <template #node>
        <svg
          v-if="checked"
          xmlns="http://www.w3.org/2000/svg"
          aria-hidden="true"
          focusable="false"
          viewBox="0 0 24 24"
          class="u-dark-svg"
        >
          <path
            d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"
          ></path>
        </svg>
        <svg
          v-else
          xmlns="http://www.w3.org/2000/svg"
          aria-hidden="true"
          focusable="false"
          viewBox="0 0 24 24"
          class="u-light-svg"
        >
          <path
            d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"
          ></path>
          <path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path>
          <path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path>
          <path
            d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"
          ></path>
          <path
            d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"
          ></path>
          <path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path>
          <path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path>
          <path
            d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"
          ></path>
          <path
            d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"
          ></path>
        </svg>
      </template>
    </Switch>
  </div>
</template>
<style lang="less" scoped>
.u-theme-switch {
  :deep(.switch-checked) {
    background: #faad14;
    &:hover:not(.disabled) {
      background: #e8b339;
    }
  }
}
.u-dark-svg {
  width: 12px;
  height: 12px;
  fill: #fff;
}
.u-light-svg {
  width: 12px;
  height: 12px;
  fill: rgba(60, 60, 67, 0.75);
}
</style>
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue中,可以通过使用开关组件来实现开关动画。根据提供的引用内容,有两个不同的开关组件示例。 引用中的示例是一个自定义的开关组件,命名为toggle-switch。它通过父组件的value属性来控制开关的状态,并在开关状态改变时触发change方法。可以根据value属性的值来决定开关的开启或关闭状态。在这个示例中,并未提供具体的开关动画实现方式。 引用中的示例是一个使用了第三方开关组件Switch。它通过v-model来绑定开关的状态,使用checked属性来控制开关的选中状态。在这个示例中,并未提供具体的开关动画实现方式。 因此,从提供的引用内容来看,并没有明确的开关动画实现方式。要实现开关动画,可以根据具体需求选择使用Vue的过渡效果或者CSS动画来实现开关的过渡效果。具体的实现方式会根据开发者的需求和具体的开关组件而定。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Vue 封装 Switch开关组件](https://blog.csdn.net/pqn_cc/article/details/123816311)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Vue2开关Switch)](https://blog.csdn.net/Dandrose/article/details/122106613)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [基于JAVA spring boot VUE 在线员工考勤管理系统设计与实现](https://download.csdn.net/download/Abelon/88250457)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值