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