Element分析(组件篇)——Checkbox

_index.js

import ElCheckbox from './src/checkbox';
import ElCheckboxGroup from './src/checkbox-group.vue';

export default function install(Vue) {
  Vue.component(ElCheckboxGroup.name, ElCheckboxGroup);
  Vue.component(ElCheckbox.name, ElCheckbox);
};

export {
  ElCheckbox,
  ElCheckboxGroup
};

Checkbox-group

<template>
  <div class="el-checkbox-group">
    <slot></slot>
  </div>
</template>

checkbox-grouphtml代码十分简单,就是一个div.el-checkbox-group包裹着一个slot,没有什么好说的,但是它在script里面做了许多处理。

Watch

监听value的变化,然后会触发一个change事件,并且根据mixin中的emitter增加的dispatch来向父组件派发事件。

watch: {
  value(value) {
    this.$emit('change', value);
    this.dispatch('ElFormItem', 'el.form.change', [value]);
  }
}

dispatch

具体的讲解将在mixin篇进行讲解,简单的说是模拟vue 1.0中的$dispatch,来将事件一直向上传递。

mixins: [Emitter],

Checkbox

我们还是先分析其生命周期。

生命周期

created

创建的时候根据checked这一prop来决定是否调用addToStore方法,

methods: {
  addToStore() {
    if (
      Array.isArray(this.model) &&
      this.model.indexOf(this.label) === -1
    ) {  // 如果 model 是数组,且不包含 label,就加入label
      this.model.push(this.label);
    } else {  // 否则 model 设置为 trueLabel或者 true
      this.model = this.trueLabel || true;
    }
  }
},

checkbox组件一共有三种label,这里先列一下官方的说明,具体使用在接下来的分析中会提及:

  1. label,选中状态的值(只有在checkbox-group或者绑定对象类型为array时有效),它的值是string
  2. true-label,选中时的值,它的值是string或者number
  3. false-label,没有选中时的值,它的值是string或者number

model是一个计算属性:

computed: {
  model: {
    get() {  // 取值
      return this.isGroup
        ? this.store : this.value !== undefined  // 多选组的时候,返回store
        ? this.value : this.selfModel;  // 否则,如果 value 不是未定义,返回 value,要么返回selfModel
    },

    set(val) {  // 赋值
      if (this.isGroup) {  // 如果是多选组
        this.dispatch('ElCheckboxGroup', 'input', [val]);  // 向父组件派发事件
      } else if (this.value !== undefined) {  // value 不是未定义
        this.$emit('input', val);  // 触发 input 事件
      } else {  // 其它
        this.selfModel = val;  // 设置selfModel
      }
    }
  },

其中value是一个prop,而selfModel是一个data上的属性,store是一个计算属性:

computed: {
  store() {
    // 如果父组件是多选组,则返回它的value,否则返回当前多选的 value
    return this._checkboxGroup ? this._checkboxGroup.value : this.value;
  }
}

isGroup是另一个计算属性,它将一直向父级查找到el-checkbox-group,如果有则返回true,否则返回false

computed: {
  isGroup() {
    let parent = this.$parent;
    while (parent) {
      if (parent.$options.componentName !== 'ElCheckboxGroup') {
        parent = parent.$parent;
      } else {
        this._checkboxGroup = parent;
        return true;
      }
    }
    return false;
  },
}

label

多选最外面是一个label

<label class="el-checkbox">
</label>

然后是两个span,一个是input部分,另一个是label部分。

el-checkbox__input

el-checkbox__input最外层也是一个span,并在上面设置了动态的class

<span class="el-checkbox__input"
  :class="{
    'is-disabled': disabled,  // 这是prop,控制是否可用
    'is-checked': isChecked,  // 这是一个计算属性
    'is-indeterminate': indeterminate,  // 这是prop,用来控制样式
    'is-focus': focus  // 这是data属性,用来控制是否聚焦
  }"
>
</span>

其中isChecked的设置如下:

computed: {
  isChecked() {
    if ({}.toString.call(this.model) === '[object Boolean]') {  // 如果 model 是布尔型
      return this.model;  // 直接返回 model
    } else if (Array.isArray(this.model)) {  // 如果 model 是数组
      return this.model.indexOf(this.label) > -1;  // 返回其中是否包含 label
    } else if (this.model !== null && this.model !== undefined) {  // 如果 model 不是null,也不是 undefined
      return this.model === this.trueLabel;  // 返回 model 是否完全等价于 trueLabel
    }
  },
}

el-checkbox__inner

然后是用来表示前面对勾的span,它 主要通过css来控制对勾的显示。

<span class="el-checkbox__inner"></span>

input

然后是传统的input,它的typecheckbox,但是这个input并不会显示,而且会根据传递的prop有两种不同的input

<input
  v-if="trueLabel || falseLabel"
  class="el-checkbox__original"
  type="checkbox"
  :name="name"
  :disabled="disabled"
  :true-value="trueLabel"
  :false-value="falseLabel"
  v-model="model"
  @change="$emit('change', $event)"
  @focus="focus = true"
  @blur="focus = false">
<input
  v-else
  class="el-checkbox__original"
  type="checkbox"
  :disabled="disabled"
  :value="label"
  :name="name"
  v-model="model"
  @change="$emit('change', $event)"
  @focus="focus = true"
  @blur="focus = false">

它们不同的地方是,前者使用了trueLabelfalseLabel,后者使用了label它们都通过v-model绑定了model,在change的时候都会派发change事件,聚焦的时候会设置focustrue

el-checkbox__label

标签部分可以通过匿名slot或者label进行设置,前者具有优先权。

<span class="el-checkbox__label" v-if="$slots.default || label">
  <slot></slot>
  <template v-if="!$slots.default">{{label}}</template>
</span>
```

> 注:这里明显看出来,这和之前不是同一个人写的,这里值得注意的是`slot`内部的内容,在没有传入`slot`才会显示,因此不同特别做一个处理,也可能是有其他我没有考虑到的原因,如果以后发现了,会回来修正。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,475评论 4 372
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,744评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,101评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,732评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,141评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,049评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,188评论 2 320
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,965评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,716评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,867评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,341评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,663评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,376评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,200评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,990评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,179评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,979评论 2 279

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,111评论 18 139
  • _index.js 单选框内部一共有三个组件:el-radio、el-radio-button和el-radio-...
    liril阅读 45,785评论 4 6
  • 下载安装搭建环境 可以选npm安装,或者简单下载一个开发版的vue.js文件 浏览器打开加载有vue的文档时,控制...
    冥冥2017阅读 5,986评论 0 42
  • 有人说:“充实而自律的人最有魅力,也最有活力,这是生命和激情迸发的结果。而寂寞、无聊的人总是看着非常颓废,因为他们...
    逐梦水乡阅读 634评论 10 30
  • 过完这个暑假,就要大四了,大四上完两个月的课就要去实习,想想在校时间真的不多了。回首大学三年生活,收获了很多,也留...
    惟一刀阅读 1,693评论 1 6