# 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>