Vue实现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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 配置参数
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
点击查看 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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
上次更新: 2021-05-10 14:08:54