element-ui checkbox组件源码学习

2018年10月28日Web前端

来看下比较常用的,且和radio比较类似的checkbox组件。

一、html部分

整个html部分与radio比较类似,简单的来看下。

最外层时label,且有配置控制着border、disabled、整个checkbox的大小。

往内部是两个span,一个是checkbox前的勾选框,后一个span是checkbox后显示的文字。 第一个span中,class是el-checkbox__inner的span就是checkbox元素框的实现,而after伪元素则是配合实现选中状态的。后面两个input元素主要是为了当给定ture与false值时,需要给input加上true-value与false-value两个属性值。

后一个span则是放checkbox对应的勾选值的。默认是优先显示slot中的值的,如果没有,则显示当前checkbox的label值。

二、JS部分

按照属性看下,

name

名称

mixins

混入了事件的broadcast与dispatch事件传播机制。

inject

注入elForm与elFormItem对象,防止单用时取值出错。

componentName

组件名称。

data()

  • selfModel,该组件的model值。
  • focus,是否获取了焦点。
  • isLimitExceeded,判断是否超出设置的最大最小值。

computed

  • model,通过中转的方式代理当前值的获取与设置。

当我们获取model值时,

get() {
    // 如果有checkbox group父组件,则直接使用store的值,否则
    // 若本组件的value(model)值不为undefined,则返回,否则返回selfModel
    return this.isGroup
        ? this.store : this.value !== undefined
        ? this.value : this.selfModel;
}

设置model的话,会有如下操作:

set(val) {
    if (this.isGroup) {
        // 当有group父级时,需要对值的范围做判断
        this.isLimitExceeded = false;
        // 当group有min值,且要set的值小于min时,将标志变量置为true
        (this._checkboxGroup.min !== undefined &&
            val.length < this._checkboxGroup.min &&
            (this.isLimitExceeded = true));

        // 当group有max值,且要set的值大于max时,将标志变量置为true
        (this._checkboxGroup.max !== undefined &&
            val.length > this._checkboxGroup.max &&
            (this.isLimitExceeded = true));
        // 没有出现设置值超出时,触发修改checkboxgroup的model值
        this.isLimitExceeded === false &&
        this.dispatch('ElCheckboxGroup', 'input', \[val\]);
    } else {
        // 没group时,直接修改本组件的model值和selfModel值
        this.$emit('input', val);
        this.selfModel = val;
    }
}
  • isChecked(),判断该checkbox是否已经被选中了。由于model值的类型比较多,所以需要较多的判断。

    isChecked() {
    if ({}.toString.call(this.model) === '\[object Boolean\]') {
        // 如果是boolean类型的(checkbox的基本用法),直接返回就行
        return this.model;
    } else if (Array.isArray(this.model)) {
        // model是数组时,判断下当前组件的label值是否在已选择值之中
        return this.model.indexOf(this.label) > -1;
    } else if (this.model !== null && this.model !== undefined) {
        // 当trueLabel有自己的值时,需要与trueLabel校验
        return this.model === this.trueLabel;
    }
    }
  • isGroup(),是否是group,与radio的一样,向上逐层遍历。
  • store(),用于获取当前的value(model)值。
  • isDisabled(),判断当前组件是否时disabled状态。

disabled的优先级顺序,checkbox-group > 本身 > form。

  • _elFormItemSize(),获取formitem的大小。
  • checkboxSize(),checkbox大小。

props

  • value,当前checkbox选中的值。
  • label,该checkbox的值。
  • indeterminate,设置 indeterminate 状态,只负责样式控制。
  • disabled,组件是否禁用。
  • checked,组件是否已经被选中。
  • name,原生 name 属性,控制checkbox分组。
  • trueLabel,选中时的值。
  • falseLabel,没有选中时的值。
  • id,当indeterminate为真时,为controls提供相关连的checkbox的id,表明元素间的控制关系。
  • controls,当indeterminate为真时,为controls提供相关连的checkbox的id,表明元素间的控制关系。
  • border,是否显示边框。
  • size,大小,尺寸,控制图标,文字大小。

methods

  • addToStore(),用于初始化值,并保存到model中。

    addToStore() {
    if (
        Array.isArray(this.model) &&
        this.model.indexOf(this.label) === -1
    ) {
        // model是数组,且不包含当前label值时,进行添加处理
        this.model.push(this.label);
    } else {
        // 直接修改
        this.model = this.trueLabel || true;
    }
    }
  • handleChange(ev),处理checkbox改变事件。

    if (this.isLimitExceeded) return;

    首先是对限制进行判断,不在范围内不操作。

    if (ev.target.checked) {
    value = this.trueLabel === undefined ? true : this.trueLabel;
    } else {
    value = this.falseLabel === undefined ? false : this.falseLabel;
    }

    当无trueLabel,falseLabel时,选中为true,否则false,有trueLabel或falseLabel值,则使用。

随后,处理一些change事件。

created()

当组件创建时,有被选中时,触发addToStore()方法。

mounted()

if (this.indeterminate) {
    this.$el.setAttribute('aria-controls', this.controls);
}

为indeterminate元素 添加aria-controls 属性。

watch

  • value(value)

    this.dispatch('ElFormItem', 'el.form.change', value);

    当前checkbox选中改变时,触发向上广播到formitem,触发el.form.change事件。

带注释的源码下载:checkbox.vue