vue.js怎么实现这种切换功能?

clipboard.png
这种功能怎么实现?

阅读 5.2k
3 个回答

用绑定不同class的方法来做:

<span v-bind:class="{'left': isClose, 'right': isOpen} switcher" v-on:click="switcher"></span>
<!--这个span就是圆形开关,点击的时候触发switcher方法-->

在vue实例中写入标记和开关方法:

data: {
    isClose: true,
    isOpen: false//假设默认关闭
},
methods: {
    switcher: function() {
        //实现开关切换
        isClose = !isClose;
        isOpen = !isOpen;
    }
}

css样式:

.switcher {
    transition: left 0.8s;
}

.left {
    left: 0;
}

.right {
    left: 50px;//移动50px
}

这样就能通过点击时改变css属性,并配合transition来实现动态开关了。

肯定有一个布尔值的开关逻辑,初始化的时候为

switchFlag:true

当点击开关的时候

this.switchFlag=!this.switchFlag

,开关动画无非是移动圆点和改变颜色

如果要做成组件,prop应该接收一个开关逻辑

父组件:

<my-switch :flag='switchFlag1'></my-switch>
<my-switch :flag='switchFlag2'></my-switch>

<div v-if='switchFlag1'>开</div>
<div v-else>关</div>

子组件接收一个

props:['flag']

再写逻辑。

只给个思路,其实很多组件库都有开关

代码:
父组件:

<template>
    <div>
         <mySwitch :flag=switchFlag @changeFlag="changeFlag"></mySwitch>
         {{status}}
    </div>
</template>

<script>
    import mySwitch from './my-btn.vue'
    export default {
        data(){
            return{
                switchFlag:false
            }
        },
        computed:{
            status(){
                return this.switchFlag?'开':'关'
            }
        },
        components:{mySwitch},
        methods:{
            changeFlag(){
                this.switchFlag=!this.switchFlag;
            }
        }
    }
</script>

子组件:

<template>
    <div>
        <div class="switch-panel">
            <span class="switch-icon" :class="{'switch-on':flag,'switch-close':!flag}" @click='changeSwitch'></span>
        </div>
    </div>
</template>

<script>
    export default {
        props:['flag'],
        methods:{
            changeSwitch(){
                this.$emit('changeFlag')
            }
        }

    }
</script>

<style>
    .switch-panel{width: 50px;height: 20px;border: 1px solid #e4e4e4;border-radius: 20px;position: relative;}
    .switch-icon{display: block;width: 16px;height:16px;border-radius: 8px;top: 1px;left: 2px;cursor: pointer;position: absolute;transition: all .5s}
    .switch-on{background-color: green;left:30px;}
    .switch-close{background: #d4d4d4;}
</style>

效果:

clipboard.png

clipboard.png

上一个小 demo ,引入方式自行修改

switch.html

<div class="switch">
    <span class="switch-input">
        <input type="checkbox"  :false-value=0 :true-value=1 v-model="val">
        <span class="input-box"></span>
    </span>
    <div class="switch-label"><slot></slot></div>
</div>

switch.js

/*
    switch切换
*/

var vue = require('vue.js');

module.exports = vue.component('switch',{
    template:__inline('./switch.html'),
    props:{
        val:{
            type:[Number,String],
            require:true,
            twoWay: true
        }
    },
    data:function(){
        return {};
    }
});

switch.less

.switch {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    vertical-align: middle;
    .switch-input{
        position: relative;
        width: 52px;
        height: 32px;
        input{
            position: absolute;
            left: 0;
            top: 0;
            width: 50px;
            height: 30px;
            z-index: 99;
            cursor: pointer;
            display: inline-block;
            -webkit-appearance: none;
            -moz-appearance: none;
            appearance: none;
            opacity: 0;
            &:focus{
                outline: none;
            }
        }
        input:checked + .input-box{
            border-color: #26a2ff;
            background-color: #26a2ff;
            &::before {
                -webkit-transform: scale(0);
                transform: scale(0);
            }
            &::after {
                -webkit-transform: translateX(20px);
                transform: translateX(20px);
            }
        }
        .input-box {
            position: absolute;
            cursor: pointer;
            width: 52px;
            height: 32px;
            border: 1px solid #d9d9d9;
            outline: 0;
            border-radius: 16px;
            box-sizing: border-box;
            background: #d9d9d9;
            &::after,
            &::before{
                content: "";
                top: 0;
                left: 0;
                position: absolute;
                -webkit-transition: -webkit-transform .3s;
                transition: -webkit-transform .3s;
                transition: transform .3s;
                transition: transform .3s, -webkit-transform .3s;
                border-radius: 15px;
            }
            &::after{
                width: 30px;
                height: 30px;
                background-color: #fff;
                box-shadow: 0 1px 3px rgba(0, 0, 0, .4);
            }
            &::before{
                width: 50px;
                height: 30px;
                background-color: #fdfdfd;
            }
        }
    }

    .switch-label {
        margin-left: 10px;
        display: inline-block;
        &:empty {
            margin-left: 0;
        }
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题