vue 可选按钮_Vue自定义单选按钮和复选框组件

本文介绍了如何在Vue中实现自定义的单选按钮和复选框组件,利用原生的radio和checkbox,通过覆盖样式实现。组件支持flex布局,具有兼容性限制,适用于不使用外部UI框架的场景。文中提供了详细的代码实现,包括单选和复选框的样式及交互逻辑。
摘要由CSDN通过智能技术生成

“ 做好自己就好了呀 ”

问题

前段时间接到一个任务,需要做一个自定义的单选和多选按钮,但是之前都是用现成的UI框架,都不用自己写样式,直接一套就是干!但是进公司后,发现部门不适用外部UI框架,好吧,那我就自己写呗!

构思

我想到的办法是运用原生的radio和CheckBox,再通过样式覆盖的方式。

兼容性

由于在写组件时使用了flex布局,so 低版本浏览器不支持的哈,具体有关flex的知识可以学习一下阮大佬的博客:Flex 布局教程:语法篇

废话不多说上代码

:class="{'column':isColumn}">

:key=index

class="check-box"

:class="{'width100':isColumn}"

@click="checkBox(index)"

v-show="!item.isShow">

:style="item.isChecked?propsStyle:''">

:value="item.value">

export default {

name: "checkbox",

data() {

return {

propsStyle: {

border: "1px solid " + this.color,

background: this.color

}

};

},

props: {

/**

items实例:[{name:'选项一',isChecked:false}],

name:可以是html,

需要显示和隐藏的加上isShow字段,true为隐藏,如下:

[{name:'选项一',isChecked:false,isShow:false}]

*/

items: {

type: Array,

default: function() {

return [];

}

},

// 已选框的颜色透明度

opacity: {

type: Boolean,

default: false

},

// flex布局纵轴方向

isColumn: {

type: Boolean,

default: false

},

// 最大选项数

limit: {

type: Number,

default: 2

},

// 已选项框的背景色

color: {

type: String,

default: "#65aef7"

}

},

watch: {

color(newval, oldval) {

if (newval != oldval) {

}

}

},

methods: {

checkBox(index) {

let count = 0;

for (let i = 0; i < this.items.length; i++) {

if (this.items[i].isChecked == true) {

count++;

}

}

if (count >= this.limit && !this.items[index].isChecked) {

this.$emit("canNotAdd", false);

return;

}

// 将所选项的value值传出去,并勾选

/* 也可将这句代码放在父组件调用这个事件的地方,可以使得复选框智能在特定条件下被选中*/

this.$set(this.items[index], "isChecked", !this.items[index].isChecked);

// this.items[index].isChecked = !this.items[index].isChecked;

this.$emit("checkBox", index);

}

}

};

.check-boxs {

display: flex;

display: -webkit-flex;

justify-content: space-between;

align-items: center;

margin: 5px 0;

color: #545454;

font-size: 12px;

}

.column {

flex-direction: column;

justify-content: flex-start;

}

.width100 {

width: 100%;

display: flex;

display: -webkit-flex;

justify-content: space-between;

height: 24px;

align-items: flex-start;

padding-right: 40px;

box-sizing: border-box;

}

.check-box {

position: relative;

cursor: pointer;

}

.check-box input {

vertical-align: middle;

margin-top: -2px;

margin-bottom: 1px;

/* 前面三行代码是为了让checkbox按钮与文字对齐 */

width: 12px;

height: 12px;

appearance: none; /*清楚默认样式*/

-webkit-appearance: none;

opacity: 0;

outline: none;

cursor: pointer;

/* 注意不能设置为display:none*/

}

/* 选项框的样式修改 */

.checkbox-icon {

width: 12px;

height: 12px;

position: absolute;

top: 1px;

z-index: 0;

border-radius: 2px;

background-color: #fff;

border: 1px solid #c9c9c9;

box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.15);

cursor: pointer;

}

.checkbox-input {

border: 1px solid #65aef7;

background-color: #65aef7;

}

.opacity {

opacity: 0.5;

}

.checkbox-on {

position: absolute;

left: 4px;

top: 1px;

width: 3px;

height: 7px;

border-right: 2px solid #fff;

border-bottom: 2px solid #fff;

transform: rotate(45deg);

}

:key=index

@click="radioOn(index)"

class="single">

v-if="item.isChecked"

:style="item.isChecked?propsStyle:''">

:name="item.name"

:id="item.value"

:value="item.value"

v-model="radio">

export default {

name: "Radio",

data() {

return {

radio: 0,

propsStyle: {

background: this.color

}

};

},

/*itemsRadio: [

{ name: "杭州", value: 0, isChecked: true },

{ name: "上海", value: 1, isChecked: false },

{ name: "北京", value: 2, isChecked: false }

]*/

props: {

items: {

type: Array,

default: function() {

return [];

}

},

color: {

type: String,

default: "#65aef7"

}

},

methods: {

radioOn(index) {

this.items.forEach(key => {

key.isChecked = false;

});

this.items[index].isChecked = true;

this.$emit("radioOn", index);

}

}

};

.radio-container {

display: flex;

display: -webkit-flex;

justify-content: space-between;

align-items: center;

font-size: 12px;

cursor: pointer;

}

.single {

position: relative;

display: flex;

display: -webkit-flex;

align-items: center;

cursor: pointer;

}

input {

width: 12px;

height: 12px;

appearance: none; /*清楚默认样式*/

-webkit-appearance: none;

opacity: 0;

outline: none;

cursor: pointer;

vertical-align: middle;

margin-top: -2px;

margin-bottom: 1px;

}

.outer {

height: 12px;

width: 12px;

display: flex;

display: -webkit-flex;

justify-content: center;

align-items: center;

border: 1px solid #ccc;

border-radius: 999px;

position: absolute;

top: 1px;

z-index: 0;

}

.inner {

background-color: green;

width: 6px;

height: 6px;

border-radius: 999px;

}

以上两个均以组件形式调用哈,只要在父组件中传入相应数据就可以看到效果哦

代码若有瑕疵,请指出,轻喷。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值