element源碼分析-checkbox多選框,感受邏輯跟單選框很像,來看看吧。javascript
checkbox多選框和單選框同樣也分爲三部分
html
至關於把checkbox和checkboxButton造成一個組
java
<div class="el-checkbox-group" role="group" aria-label="checkbox-group">
<!-- 插槽:用來接收checkbox或checkbox-button -->
<slot></slot>
</div>
複製代碼
默認爲空,若在form組件中嵌套使用並form組件注入了elFormItem則有值element-ui
inject: {
elFormItem: {
default: ''
}
}
複製代碼
computed: {
// 控制大小
_elFormItemSize() {
return (this.elFormItem || {}).elFormItemSize;
},
checkboxGroupSize() {
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
}
}
複製代碼
checkboxGroupSize會在checkbox
和checkboxButton
中用到數組
watch: {
// 監聽value 向上尋找form組件發佈el.form.change事件暴露value(數組)
value(value) {
this.dispatch('ElFormItem', 'el.form.change', [value]);
}
}
複製代碼
props: {
// 與v-model綁定
value: {},
// 是否禁用
disabled: Boolean,
// 最少勾選長度
min: Number,
// 最大勾選長度
max: Number,
// 大小
size: String,
// 邊框及背景填充色
fill: String,
// 文字顏色
textColor: String
}
複製代碼
有些屬性checkbox和checkboxButton組件會用到dom
<label class="el-checkbox" :class="[ border && checkboxSize ? 'el-checkbox--' + checkboxSize : '', { 'is-disabled': isDisabled }, { 'is-bordered': border }, { 'is-checked': isChecked } ]" role="checkbox" :aria-checked="indeterminate ? 'mixed': isChecked" :aria-disabled="isDisabled" :id="id" >
</label>
複製代碼
<span class="el-checkbox__input" :class="{ 'is-disabled': isDisabled, 'is-checked': isChecked, 'is-indeterminate': indeterminate, 'is-focus': focus }" aria-checked="mixed" >
<span class="el-checkbox__inner"></span>
<!-- 有trueLabel或falseLabel時展現 -->
<input ... v-if="trueLabel || falseLabel" ... >
<!-- 無trueLabel和falseLabel時展現 -->
<input v-else ... >
</span>
複製代碼
<span class="el-checkbox__label" v-if="$slots.default || label">
<slot></slot>
// 有插槽內容顯示插槽 無直接顯示label
<template v-if="!$slots.default">{{label}}</template>
</span>
複製代碼
created() {
// 若是當前勾選 調用addToStore(至關於選中與model值對應)
this.checked && this.addToStore();
},
mounted() {
// 若是有被選中又不是全選
// 爲indeterminate元素 添加aria-controls 屬性
if (this.indeterminate) {
// controls對應id,表示元素之間的控制關係
this.$el.setAttribute('aria-controls', this.controls);
}
}
複製代碼
addToStore方法源碼分析
addToStore() {
// 若是model是數組而且不包含當前的選項,把當前選項push到model中
if (
Array.isArray(this.model) &&
this.model.indexOf(this.label) === -1
) {
this.model.push(this.label);
// 不然 爲傳入選中值或true
} else {
this.model = this.trueLabel || true;
}
}
複製代碼
// 是否被選中
isChecked() {
// model是Boolean類型
if ({}.toString.call(this.model) === '[object Boolean]') {
// 直接返回model
return this.model;
// 數組類型
} else if (Array.isArray(this.model)) {
// 當前的label在model中爲true不在爲false
return this.model.indexOf(this.label) > -1;
// model存在 返回是否與props的trueLabel全等
} else if (this.model !== null && this.model !== undefined) {
return this.model === this.trueLabel;
}
}
複製代碼
// 向上找checkbox-group組件找到返回true 未找到返回false
isGroup() {
let parent = this.$parent;
while (parent) {
if (parent.$options.componentName !== 'ElCheckboxGroup') {
parent = parent.$parent;
} else {
this._checkboxGroup = parent;
return true;
}
}
return false;
}
複製代碼
isDisabled() {
// 取決於 checkbox-group的disabled props的disabled form注入的disabled
return this.isGroup
? this._checkboxGroup.disabled || this.disabled || (this.elForm || {}).disabled
: this.disabled || (this.elForm || {}).disabled;
},
_elFormItemSize() {
return (this.elFormItem || {}).elFormItemSize;
},
checkboxSize() {
// 取決於傳入的size form組件注入的size 全局配置size
const temCheckboxSize = this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
// 若是被checkbox-group組件包裹,優先checkbox-group組件的size
return this.isGroup
? this._checkboxGroup.checkboxGroupSize || temCheckboxSize
: temCheckboxSize;
}
複製代碼
// checkbox-group組件實例的value或當前value
store() {
return this._checkboxGroup ? this._checkboxGroup.value : this.value;
}
複製代碼
// v-model的值
model: {
// 取值
get() {
// 被checkbox-group包裹則取store,當前value有值則取value不然selfModel
return this.isGroup
? this.store : this.value !== undefined
? this.value : this.selfModel;
},
// 賦值
set(val) {
// 被checkbox-group包裹
if (this.isGroup) {
this.isLimitExceeded = false;
// 若賦值長度小於checkbox-group的min 突破限制
(this._checkboxGroup.min !== undefined &&
val.length < this._checkboxGroup.min &&
(this.isLimitExceeded = true));
// 若賦值長度大於checkbox-group的max 突破限制
(this._checkboxGroup.max !== undefined &&
val.length > this._checkboxGroup.max &&
(this.isLimitExceeded = true));
// 沒有突破限制 向上找到checkbox-group組件發佈input事件暴露val(數組形式)
this.isLimitExceeded === false &&
this.dispatch('ElCheckboxGroup', 'input', [val]);
} else {
// 沒有被checkbox-group包裹 直接發佈input事件暴露val
this.$emit('input', val);
// 給selfModel賦值val
this.selfModel = val;
}
}
}
複製代碼
// input的change事件
handleChange(ev) {
// 突破限制 直接return
if (this.isLimitExceeded) return;
let value;
if (ev.target.checked) {
// 被選中 給value賦值 有trueLabel則賦值trueLabel 無則賦值true
value = this.trueLabel === undefined ? true : this.trueLabel;
} else {
// 未被選中 給value賦值 有falseLable則賦值falseLabel 無則false
value = this.falseLabel === undefined ? false : this.falseLabel;
}
// 發佈change方法暴露value及和event對象
this.$emit('change', value, ev);
// dom渲染完成後 若是被checkbox-group組件包裹 則發佈change事件,暴露checkbox-group組件實例的value(數組)
this.$nextTick(() => {
if (this.isGroup) {
this.dispatch('ElCheckboxGroup', 'change', [this._checkboxGroup.value]);
}
});
}
複製代碼
watch: {
// 監聽value變化,向上找到form組件則發佈el.form.change事件暴露出value
value(value) {
this.dispatch('ElFormItem', 'el.form.change', value);
}
}
複製代碼
dispatch: 從mixins混入進來的方法,向上尋找(指定組件,發佈指定事件,暴露指定值)ui
import Emitter from 'element-ui/src/mixins/emitter'
複製代碼
與checkbox基本一致,多了button相關樣式,computed中的activeStyle,受checkbox-group的fill控制
this