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