近期根據業務須要簡單寫了個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: []
}複製代碼
最終看下頁面上展現的效果:
能夠選擇、取消,對應的灰色爲不可修改選項。總體功能和方法都比較簡單,樣式方面使用時能夠根據需求本身進行優化。
對於組件開發,我的以爲不管大小,對於基礎和邏輯都是一個簡單的鍛鍊過程,尤爲是開發服用性較強的組件,對邏輯和使用場景的考慮須要更加全面。