参数支持:
一、switch组件
- 基本框架和样式
<template>
<div>
<span class="x_switch_core">
<span class="x_switch_btn">
</span>
</span>
</div>
</template>
<script>export default {
name: 'TwoSwitch',
}</script>
<style lang="scss" scoped>.x_switch {
display: inline-flex;
align-items: center;
position: relative;
font-style: 14px;
line-height: 20px;
height: 20px;
vertical-align: middle;
.x-switch-input {
position: absolute;
width: 0;
height: 0;
opacity: 0;
margin: 0;
}
.x_switch_core {
margin: 0;
display: inline-block;
position: relative;
width: 40px;
height: 20px;
border: 1px solid #dcdfe6;
outline: none;
border-radius: 10px;
box-sizing: border-box;
background: #dcdfe6;
cursor: pointer;
transition: border-color 0.3s, background-color 0.3s;
vertical-align: middle;
.x_switch_btn {
position: absolute;
top: 1px;
left: 1px;
border-radius: 100%;
transition: all 0.3s;
width: 16px;
height: 16px;
background: #fff;
}
}
}
// 选中的样式
.x-switch-checked {
.x_switch_core {
border-color: #409eff;
background-color: #409eff;
.x_switch_btn {
transform: translateX(20px);
}
}
}</style>
- 双向数据绑定
在父组件中使用v-model绑定数据,在子组件内获取value属性,并定义一个点击事件(绑定回调函数)与父组件通信,改变父组件中的绑定值。
- 父组件中:
<two-switch v-model="swFlag"></two-switch>
- 子组件中,点击时改变is-checked类状态看,触发滑块滑动 :
<template>
<div
@click="switchClick"
class="x_switch"
:class="{'x-switch-checked':value}">
<span class="x_switch_core">
<span class="x_switch_btn">
</span>
</span>
<input type="checkbox" class="x-switch-input" :name="name" ref="input">
</div>
</template>
将input事件触发出去,点击取反:
此时点击页面中的switch,value值会更新。
methods:{
switchClick(){
this.$emit('input',!this.value)
}
}
此时,页面上组件是这个效果,value值已经实现双向绑定。
但是,我们想要看到页面上组件的切换后的效果。可以给switch组件添加滑动样式。
滑动样式:
// 选中的样式
.x-switch-checked {
.x_switch_core {
border-color: #409eff;
background-color: #409eff;
.x_switch_btn {
transform: translateX(20px);
}
}
}
此时,点击switch时,可以改变颜色。
- 实现switch 颜色自定义
首先,需要父组件传入颜色的值,在子组件中接收。
- 父组件传递颜色参数:
<two-switch
v-model="swFlag"
active-color="yellow"
inactive-color="red">
</two-switch>
- 子组件中定义ref="core"以确定要改变颜色的dom节点。
<div
@click="switchClick"
class="x_switch"
:class="{'x-switch-checked':value}">
<span class="x_switch_core" ref="core">
<span class="x_switch_btn">
</span>
</span>
<input type="checkbox" class="x-switch-input" :name="name" ref="input">
</div>
通过mouted钩子,在刚进入页面以及value改变时对颜色进行改变:
props:{
value:{
type: Boolean,
default: false
},
name:{
type: String,
default: ''
},
activeColor: {
type: String,
default: ''
},
inactiveColor: {
type: String,
default: ''
}
},
mounted(){
this.setColor()
},
methods:{
switchClick(){
// v-model 绑定的是 input 事件,子传父直接用input事件;如果不用input,则需要在父组件中用@事件 + v-bind绑定值 进行接收值,
// 触发父组件中的事件 ,并传值 (子传父)
this.$emit('input',!this.value)
// 等待父组件的value值更新dom节点后 再调用
this.$nextTick(()=>{
this.setColor()
})
},
// 修改开关颜色
setColor(){
if(this.activeColor || this.inactiveColor){
let color = this.value ? this.activeColor : this.inactiveColor
this.$refs.core.style.borderColor = color
this.$refs.core.style.backgroundColor = color
}
}
}
- 添加name属性
当用户使用switch组件时,实际上是把它当成表单元素来使用。可能会用到组件的name属性,因此需要在switch组件中添加一个checkbox,并且当值改变的时候,也需要设置checkbox的value值。
switch组件中加入input标签,并接收父组件传过来的name值:
<template>
<div
@click="switchClick"
class="x_switch"
:class="{'x-switch-checked':value}">
<span class="x_switch_core" ref="core">
<span class="x_switch_btn">
</span>
</span>
<input type="checkbox" class="x-switch-input" :name="name" ref="input">
</div>
</template>
接收name值:
props:{
name:{
type: String,
default: ''
}
},
父组件中,传递 name值:
<two-switch
v-model="swFlag"
active-color="yellow"
inactive-color="red"
name="username"></two-switch>
设置标签样式,因为input标签只作为name绑定使用,因此将其隐藏起来:
// 隐藏input标签
.x-switch-input {
position: absolute;
width: 0;
height: 0;
opacity: 0;
margin: 0;
}
在页面加载和点击时(当value的值改变时)修改input的checked值,保证和switch组件的value值同步:
mounted(){
this.setColor()
},
methods:{
switchClick(){
// v-model 绑定的是 input 事件,子传父直接用input事件;如果不用input,则需要在父组件中用@事件 + v-bind绑定值 进行接收值,
// 触发父组件中的事件 ,并传值 (子传父)
this.$emit('input',!this.value)
// 等待父组件的value值更新dom节点后 再调用
this.$nextTick(()=>{
this.setColor()
})
},
// 修改开关颜色
setColor(){
if(this.activeColor || this.inactiveColor){
let color = this.value ? this.activeColor : this.inactiveColor
this.$refs.core.style.borderColor = color
this.$refs.core.style.backgroundColor = color
}
// 控制checkbox的checked(使input的值与value同步)
this.$refs.input.checked = this.value
}
}
最后,附上switch组件的全部代码:
<template>
<div
@click="switchClick"
class="x_switch"
:class="{'x-switch-checked':value}">
<span class="x_switch_core" ref="core">
<span class="x_switch_btn">
</span>
</span>
<input type="checkbox" class="x-switch-input" :name="name" ref="input">
</div>
</template>
<script>export default {
name: 'TwoSwitch',
data(){
return {
}
},
props:{
value:{
type: Boolean,
default: false
},
name:{
type: String,
default: ''
},
activeColor: {
type: String,
default: ''
},
inactiveColor: {
type: String,
default: ''
}
},
mounted(){
this.setColor()
},
methods:{
switchClick(){
// v-model 绑定的是 input 事件,子传父直接用input事件;如果不用input,则需要在父组件中用@事件 + v-bind绑定值 进行接收值,
// 触发父组件中的事件 ,并传值 (子传父)
this.$emit('input',!this.value)
// 等待父组件的value值更新dom节点后 再调用
this.$nextTick(()=>{
this.setColor()
})
},
// 修改开关颜色
setColor(){
if(this.activeColor || this.inactiveColor){
let color = this.value ? this.activeColor : this.inactiveColor
this.$refs.core.style.borderColor = color
this.$refs.core.style.backgroundColor = color
}
// 控制checkbox的checked(使input的值与value同步)
this.$refs.input.checked = this.value
}
}
}</script>
<style lang="scss" scoped>.x_switch {
display: inline-flex;
align-items: center;
position: relative;
font-style: 14px;
line-height: 20px;
height: 20px;
vertical-align: middle;
// 不让input显示出来
.x-switch-input {
position: absolute;
width: 0;
height: 0;
opacity: 0;
margin: 0;
}
.x_switch_core {
margin: 0;
display: inline-block;
position: relative;
width: 40px;
height: 20px;
border: 1px solid #dcdfe6;
outline: none;
border-radius: 10px;
box-sizing: border-box;
background: #dcdfe6;
cursor: pointer;
transition: border-color 0.3s, background-color 0.3s;
vertical-align: middle;
.x_switch_btn {
position: absolute;
top: 1px;
left: 1px;
border-radius: 100%;
transition: all 0.3s;
width: 16px;
height: 16px;
background: #fff;
}
}
}
// 选中的样式
.x-switch-checked {
.x_switch_core {
border-color: #409eff;
background-color: #409eff;
.x_switch_btn {
transform: translateX(20px);
}
}
}</style>
如何在父组件中使用?
引入并注册之后,添加:
<switch
v-model="swFlag"
active-color="yellow"
inactive-color="red"
name="username"></switch>
data(){
return {
swFlag: false;
}
}