【vue自定义组件】基于element-ui 实现一个单选开关
前言
佛祖保佑, 永无bug
。Hello 大家好!我是海的对岸!
实际开发中,碰到一个单选开关的效果,这个开关的效果,原型图上是用开关来做的,不是传统的单选框,网上没有现成的(可能有,但是我没找到),这个功能在日常工作中很常见,这里刚好碰到了,手动实现了一下,整理记录下。
期望
预期的效果如下:
简单说明下(功能简述):
- 4个开关(最后一个禁用了,不用考虑,就当共有3个开关参加交互)
- 就当是3个开关参与交互,打开其中一个开关,其他另外2个就关闭了
- 当某个开关处于打开状态,再次点击这个已经打开的关闭,不让他关闭,只有选择其他的开关时,之前已经打开的才会关闭
实现思路
该功能实现的难点在于,如何让已经打开的关闭,不让它关闭?
我实操下来,发现有2种方法
实现方式(1)desabled
第一种: 结合 :disabled
属性和事件处理逻辑来实现,使用 disabled属性,鼠标悬停在开关上面,会有一种 禁用的图标
出来,而且开关也会变成灰色,因为禁用的效果,自然而然,也就不能继续点下去了。这种做法呢,会有个样式上的变化。
实现的效果如下:
上代码:(当前使用vue2 开发):
html部分
<template>
...
<div class="map-tool-item">
<div>常规</div>
<el-switch
class="map-switch"
active-color="#266bff"
v-model="switch_Vector"
:disabled="isVectorDisabled"
@change="change_Vector"/>
</div>
<div class="map-tool-item">
<div>卫星影像</div>
<el-switch
class="map-switch"
active-color="#266bff"
v-model="switch_Img"
@change="change_Img"
:disabled="isImgDisabled"/>
</div>
<div class="map-tool-item">
<div>深色地图</div>
<el-switch
class="map-switch"
active-color="#266bff"
v-model="switch_dark"
@change="change_dark"
:disabled="isDarkDisabled"/>
</div>
...
</template>
js部分
...
data() {
return {
switch_Vector: true, // 显示矢量图
switch_Img: false, // 是否加载影像图
switch_dark: false, // 是否加载深色地图图
isVectorDisabled: true, // 是否禁用矢量开关
isImgDisabled: false, // 是否禁用影像开关
isDarkDisabled: false, // 是否禁用深色地图开关
};
},
methods: {
// 是否开启矢量地图
change_Vector() {
if (this.switch_Vector) {
// 当前开关打开1,设置自己 和 其他 2个开关的 开关状态
this.switch_Img = false;
this.switch_dark = false;
// 当前开关打开2,设置自己 和 其他 2个开关的 是否禁用状态
this.isVectorDisabled = true;
this.isImgDisabled = false;
this.isDarkDisabled = false;
// 处理地图逻辑...
} else {
// 当前开关关闭,设置自己 和 其他 2个开关的 开关状态
this.isVectorDisabled = false;
this.isImgDisabled = true;
this.isDarkDisabled = true;
}
},
// 是否开启影像地图
change_Img() {
if (this.switch_Img) {
this.switch_Vector = false;
this.switch_dark = false;
this.isImgDisabled = true;
this.isVectorDisabled = false;
this.isDarkDisabled = false;
// 处理地图逻辑...
} else {
this.isImgDisabled = false;
this.isVectorDisabled = true;
this.isDarkDisabled = true;
}
},
// 是否开启深色地图
change_dark() {
if (this.switch_dark) {
this.switch_Vector = false;
this.switch_Img = false;
this.isDarkDisabled = true;
this.isVectorDisabled = false;
this.isImgDisabled = false;
// 处理地图逻辑...
} else {
this.isDarkDisabled = false;
this.isVectorDisabled = true;
this.isImgDisabled = true;
}
},
}
功能是有了,但是项目经理,觉得这个禁用的图标显示在上面,置灰了一层,图标点击之后,灰蒙蒙的一层。觉得有点丑,能不能就显示正常的颜色,用户点了之后,继续点下去,发现不能点,就会知道要去点下一个开关了,想让我整成这样的效果。那行,第二种实现方法就自然而然出来了。
实现方式(2)监听 input 事件
第二种: 通过监听 input 事件
,并在事件处理函数中动态修改绑定值的方式来实现在关闭状态下能打开,但打开后不能再关闭的功能
通俗一点讲,就是 使用 input事件,触发它,让它在打开的状态下,给我自始至终都保持 true。
实现的效果如下(即开头的效果):
上代码:(当前使用vue2 开发):
html部分
<template>
...
<div class="map-tool-item">
<div>常规</div>
<el-switch
class="map-switch"
active-color="#266bff"
v-model="switch_Vector"
@input="handleSwitchInputVector"
@change="change_Vector"/>
</div>
<div class="map-tool-item">
<div>卫星影像</div>
<el-switch
class="map-switch"
active-color="#266bff"
v-model="switch_Img"
@change="change_Img"
@input="handleSwitchInputImg"/>
</div>
<div class="map-tool-item">
<div>深色地图</div>
<el-switch
class="map-switch"
active-color="#266bff"
v-model="switch_dark"
@change="change_dark"
@input="handleSwitchInputDark"/>
</div>
...
</template>
js部分
...
data() {
return {
switch_Vector: true, // 显示矢量图
switch_Img: false, // 是否加载影像图
switch_dark: false, // 是否加载深色地图图
};
},
methods: {
// 是否开启矢量地图
change_Vector() {
if (this.switch_Vector) {
this.switch_Img = false;
this.switch_dark = false;
// 处理地图逻辑...
}
},
// 是否开启影像地图
change_Img() {
if (this.switch_Img) {
this.switch_Vector = false;
this.switch_dark = false;
// 处理地图逻辑...
}
},
// 是否开启深色地图
change_dark() {
if (this.switch_dark) {
this.switch_Vector = false;
this.switch_Img = false;
// 处理地图逻辑...
}
},
// 在开关处在打开的状态下,依旧置为true
handleSwitchInputVector() {
this.switch_Vector = true;
},
// 在开关处在打开的状态下,依旧置为true
handleSwitchInputImg() {
this.switch_Img = true;
},
// 在开关处在打开的状态下,依旧置为true
handleSwitchInputDark() {
this.switch_dark = true;
},
}
这样就达到了,我们想要的效果。
两种方法,都能实现功能,但是样式上会有些出入,第一种悬停,会直接出现禁用的图标,而且也会置灰, 第二种,则是样式上没啥太大的变化,但是已经是开启状态的开关,就是点了也不会变成关闭状态。具体用哪种,看你们自己的想法。
转载自:https://juejin.cn/post/7269032845787283511