• 分享

使用vue3封装Switch开关组件

avatar avatar
364阅读 0评论 0喜欢

自己写了一个视频播放器组件,为了减少npm包的体积里面用到的组件都是自己封装的

工作中switch开关组件组件中都有,但是这个组件自己会封装吗?这篇文章教大家运用简单的html元素实现就能实现一个Vue3版本的switch组件。

先看一下图例 开关的状态

Snipaste_20210916_151623.png

<iframe height="300" style="width: 100%;" scrolling="no" title="vue3实现switch开关组件" src="https://codepen.io/xdlumia/embed/KKqZPGN?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/xdlumia/pen/KKqZPGN"> vue3实现switch开关组件</a> by xdlumia (<a href="https://codepen.io/xdlumia">@xdlumia</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 为什么说我这个组件简单呢? 先上html代码 非常简单

<template>
    <div class="d-switch" :class="{ 'is-checked': checked }">
        <input
            class="d-switch__input"
            ref="input"
            type="checkbox"
            :checked="checked"
            @change="handleInput"
            :true-value="trueValue"
            :false-value="falseValue"
        />
        <span class="d-switch_action"></span>
    </div>
</template>

这里解释一下逻辑

1.d-switch元素:最外层就是开关的盒子 用来定义背景色和宽高 通过 classis-checked控制开和关的样式 2.d-switch__input元素:仔细看一下这个开关组件里我并没有使用@click事件,是因为click事件都是通过这个input元素实现的。input的值也可以通过true-valuefalse-value 自定义 3. d-switch_action:这个元素就是开关里的圆色白点。 4. 很重要的一点,因为这个组件是通过点击input获取到当前状态,所以这里要把inputz-index设置为1,覆盖在span标签上面,然后把opacity设置为0.这样你看到的是 span标签的样式,但是你点击的其实是input触发的事件

<style lang='less' scoped>
.d-switch {
    position: relative;
    height: 18px;
    transition: background 0.2s;
    width: v-bind(width);
    background: rgb(117, 117, 117);
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
    .d-switch__input {
        position: relative;
        z-index: 1;
        margin: 0;
        width: 100%;
        height: 100%;
        opacity: 0;
    }
    .d-switch_action {
        position: absolute;
        transition: 0.2s;
        left: 2px;
        top: 2px;
        z-index: 0;
        height: 14px;
        width: 14px;
        background: #fff;
        border-radius: 50%;
    }
    &.is-checked {
        background: v-bind(activeColor);
        .d-switch_action {
            left: 100%;
            background: #fff;
            margin-left: -18px;
        }
    }
}
</style>

最后是添加props属性和事件

import { computed, ref, nextTick } from 'vue'
const props = defineProps({
    modelValue: {  //绑定值,必须等于active-value或inactive-value,默认为Boolean类型  如果是vue2 这里绑定是 `value`
        type: [Number, String, Boolean],
    },
    trueValue: { //switch 打开时的值 可以自定义组件打开的时的值 
        type: [Number, String, Boolean],
        default: true,
    },
    falseValue: { //	switch 关闭时的值  可以自定义组件关闭的时的值 
        type: [Number, String, Boolean],
        default: true,
    },
    activeColor: { //switch 打开时的背景色
        type: [String],
        default: '#409EFF',
    }
})
const emits = defineEmits(['update:modelValue', 'change'])

//获取input元素
const input = ref(null)
//判断当前组件是否是打开状态
const checked = computed(() => {
    //因为可以自定义打开和关闭的值 所以这里必须判断 v-model绑定的值 === 组件自定义打开的值
    return props.modelValue === props.trueValue
})
//input事件 获取当前input事件
const handleInput = () => {
    nextTick(() => {
        const val = input.value.checked
        emits("update:modelValue", val); // 开关点击后的状态传给v-model  
        emits("change", val); //给组件增加change 事件
    })
};

使用示例

<template>
  <div>
    获取的值{{value1}}
    <my_switch v-model="value1"></my_switch>
  </div>
</template>

<script setup>
import my_switch from "./my_switch"; //这里引入上一个文件(目录自己定)
import {ref} fron 'vue'
let value1 = ref(false)
</script>
avatar avatar

赶快写下您的第一条评论吧