近期根据业务须要简单写了个checkbox及checkboxGroup组件,使用起来还算是方便,也顺便了解了下关于v-model的用法(可参考上一篇:v-model爬坑记录)。关于组件,也没什么特别复杂的,简单说下思路,直接上代码。css
组件开发思路:sass
①、复选框从效果上看,就是是否勾选一些内容;从使用上来说,咱们须要将选中的选项对应的值传递出来,供后面使用。bash
②、基本的checkbox组件是基于input的checkbox开发的,同时为了样式相对统一将原来的input进行隐藏,经过css的 :checked 进行样式的统一。同时设置一些属性,好比是不是按钮形式、是否选中、是否不可点以及选项名称都作成能够配置的,方便后面使用。post
③、对于单独一个的复选框方法比较简单,取到对应的值传到父组件便可;flex
④、对于多个复选框,咱们将v-model绑定到了checkboxGroup组件上,对应的选中增长值、取消选中删除值方法也在父组件中,经过$emit在子组件中进行调用。优化
⑤、同时为了丰富使用场景,组件初始化的时候咱们判断是否有默认选中的值,默认选中展现为勾选,同时将对应的值取出来进行收集。ui
这就是开发这个组件基本的一个思路,下面直接上代码,对应的属性方法都有注释,直接看注释就能够很清楚了。(关于文中样式使用的rem方法和@include方法,是经过sass统必定义的单位转换和字号转换方法,可根据实际状况进行修改)this
基础的checkbox组件:spa
注:子组件的大盒子checkBoxClass实际能够去掉,这里主要是用来配置统一的文字颜色和字号,可是实际也只是基础的颜色,对于选中样式和选择框样式依旧须要经过样式覆盖方式进行修改。因此实际使用时关于样式咱们能够经过样式覆盖的方式进行重置
3d
<template>
<div class="checkbox" :class="checkBoxClass">
<div :class="isDisable ? 'checkDisable' : ''">
<div :class="isButton ? 'checkboxBtn' : 'checkboxItem'">
<input type="checkbox" :value="val" :id="label" :checked="checked" :disabled="isDisable" @change="checkChange($event)"/>
<label :for="label">{{ label }}</label>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Checkbox',
model: { prop: 'value', event: 'change' },
computed: {
/**
* 是不是复选框群组,经过父级ref是否为checkBigBox判断
*/
isGroup() {
return this.$parent.$refs && this.$parent.$refs.checkBigBox;
}
},
mounted() {
/**
* 非多选组,而且初始为选中状态时,获取选中项的值
*/
if (!this.isGroup) {
if (this.checked) {
this.$emit('change', this.val + '');
}
}
},
props: {
/**
* 外层盒子类名,能够经过属性传递配置,主要是修改文字颜色和字号。
* 如要修改选中样式、选择框颜色,能够经过样式覆盖方式,选中样式暂不考虑能够配置方式。
*/
checkBoxClass: {
type: String,
default: 'checkboxDefault'
},
/**
* 选择框是不是按钮形式,默认false
*/
isButton: {
type: Boolean,
default: false
},
/**
* 选项名称
*/
label: {
type: String,
default: '选项'
},
/**
* 选项值
*/
val: {
type: [Number, String]
},
/**
* 初始化时是否选中状态,默认false
*/
checked: {
type: Boolean,
default: false
},
/**
* 是否禁止选择,默认false
*/
isDisable: {
type: Boolean,
default: false
}
},
methods: {
/**
* 点击checkbox时触发方法,多选组时调用父组件的增长和删除方法,单独复选框时设置值和清除值
*/
checkChange(e) {
if (this.isGroup) {
if (e.target.checked) {
this.$parent.addCheck(e.target.value);
} else {
this.$parent.delCheck(e.target.value);
}
} else {
if (e.target.checked) {
this.$emit('change', e.target.value);
} else {
this.$emit('change', '');
}
}
}
}
};
</script>
<style lang="scss" scoped>
@import '../styles/mixins.scss';
.checkbox {
.checkboxItem {
margin: 0 rem(20) rem(20) 0;
input {
display: none;
}
label::before {
content: '√';
width: rem(28);
height: rem(28);
line-height: rem(28);
border: 1px solid #333;
display: inline-block;
text-align: center;
color: transparent;
margin-right: rem(6);
}
& input[type='checkbox']:checked ~ label {
color: #e20;
}
& input[type='checkbox']:checked ~ label::before {
content: '√';
color: #e20;
border: 1px solid #e20;
}
}
.checkboxBtn {
margin: 0 rem(20) rem(20) 0;
input {
display: none;
}
label {
position: relative;
padding: rem(4) rem(10);
display: block;
}
label::before {
content: '';
display: block;
width: 100%;
height: 100%;
border: 1px solid #333;
text-align: center;
color: transparent;
margin-right: rem(6);
position: absolute;
left: 0;
top: 0;
}
& input[type='checkbox']:checked ~ label {
color: #e20;
}
& input[type='checkbox']:checked ~ label::before {
content: '';
color: #e20;
border: 1px solid #e20;
}
}
.checkDisable {
.checkboxItem {
label {
color: #ccc;
cursor: not-allowed;
}
label::before {
content: '√';
border: 1px solid #ccc;
color: transparent;
}
& input[type='checkbox']:checked ~ label {
color: #ccc;
}
& input[type='checkbox']:checked ~ label::before {
content: '√';
color: #ccc;
border: 1px solid #ccc;
}
}
.checkboxBtn {
label {
color: #ccc;
cursor: not-allowed;
}
label::before {
content: '';
border: 1px solid #ccc;
color: transparent;
}
& input[type='checkbox']:checked ~ label {
color: #ccc;
}
& input[type='checkbox']:checked ~ label::before {
content: '';
color: #ccc;
border: 1px solid #ccc;
}
}
}
}
.checkboxDefault {
@include fontSize(24);
color: #333;
}
</style>复制代码
复选框组:
注:关于复选框组,其实咱们并无调用基础的checkbox,只是定义了一个大盒子,同时同slot占位。实际做用就是用来收集选中的数据以及处理复选框组对应的一些方法。
<template>
<div ref="checkBigBox" class="checkboxGroup">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'CheckBoxGroup',
props: {
value: {
type: Array
}
},
model: {
prop: 'value',
event: 'change'
},
mounted() {
/**
* 多选组时,初始化若是有默认选中项则获取对应的value值
*/
const childItem = this.$children;
let childArr = [];
childItem.map(child => {
if (child.checked) {
childArr.push(child.val + '');
}
});
this.$emit('change', [...childArr]);
},
methods: {
/**
* checkbox选中状态时,增长值方法
* 参数说明:
* @param {String} item 选中增长项的值
*/
addCheck(item) {
const { value } = this;
this.$emit('change', [...value, item]);
},
/**
* checkbox取消选中状态时,减小值方法
* 参数说明:
* @param {String} item 取消选中项的值
*/
delCheck(item) {
const { value } = this;
this.$emit('change', value.filter(val => val !== item));
}
}};
</script>
<style lang="scss" scoped>
.checkboxGroup { display: flex; flex-wrap: wrap;}
</style>复制代码
组件的使用:
/* 单独复选框使用 */
<Checkbox :label="checkOne.label" :val="checkOne.value" :checked="checkOne.checked" v-model="checkStr"></Checkbox>
/* 复选框组使用 */
<CheckBoxGroup v-model="checkBoxArr">
<Checkbox v-for="item in checkLists" :label="item.label" :val="item.value" :checked="item.checked" :isDisable="item.disable" :key="item.value" :checkBoxClass="checkBoxClass"></Checkbox>
</CheckBoxGroup>
<p>只有一项状况:{{ checkStr }}</p>
<p>复选框群组:{{ checkBoxArr }}</p>
data(){
checkOne: { label: '手机', value: 10, checked: true },
checkLists: [
{ label: '手机1', value: 0, disable: true },
{ label: '电视', value: 1 },
{ label: '洗衣机', value: 2, checked: true },
{ label: '冰箱', value: 3 },
{ label: '家用电器', value: 4, checked: true, disable: true },
{ label: '手机2', value: 5 },
{ label: '电视1', value: 6 },
{ label: '洗衣机1', value: 7, checked: true },
{ label: '冰箱1', value: 8 },
{ label: '家用电器1', value: 9 }
],
checkStr: '',
checkBoxArr: []
}复制代码
最终看下页面上展现的效果:
能够选择、取消,对应的灰色为不可修改选项。总体功能和方法都比较简单,样式方面使用时能够根据需求本身进行优化。
对于组件开发,我的以为不管大小,对于基础和逻辑都是一个简单的锻炼过程,尤为是开发服用性较强的组件,对逻辑和使用场景的考虑须要更加全面。