美文网首页Vue
深入Vue之解析ElementUI组件--button

深入Vue之解析ElementUI组件--button

作者: Lia代码猪崽 | 来源:发表于2019-09-27 11:44 被阅读0次

一、github地址

https://github.com/ElemeFE/element/blob/dev/packages/button/src/button.vue

二、文档地址

https://element.eleme.cn/#/zh-CN/component/button

三、解析过程(很多注释在源代码是不合法的,这里只是为了更直观的展示)

<template>
  <button
    class="el-button"  // 注解1
    @click="handleClick"  // 注解2
    :disabled="buttonDisabled || loading"  // 注解3
    :autofocus="autofocus"
    :type="nativeType"
    :class="[  // 注解4
      type ? 'el-button--' + type : '',
      buttonSize ? 'el-button--' + buttonSize : '',
      {
        'is-disabled': buttonDisabled,
        'is-loading': loading,
        'is-plain': plain,
        'is-round': round,
        'is-circle': circle
      }
    ]"
  >
    <i class="el-icon-loading" v-if="loading"></i>  // 注解5
    <i :class="icon" v-if="icon && !loading"></i>  // 注解6
    <span v-if="$slots.default"><slot></slot></span>  // 注解7
  </button>
</template>
<script>
  export default {
    name: 'ElButton',
    // 注解3
    inject: {
      elForm: {
        default: ''
      },
      elFormItem: {
        default: ''
      }
    },
    props: {
      type: {
        type: String,
        default: 'default'
      },
      size: String,
      icon: {
        type: String,
        default: ''
      },
      nativeType: {
        type: String,
        default: 'button'
      },
      loading: Boolean,
      disabled: Boolean,
      plain: Boolean,
      autofocus: Boolean,
      round: Boolean,
      circle: Boolean
    },
    computed: {
      _elFormItemSize() {
        return (this.elFormItem || {}).elFormItemSize;
      },
      buttonSize() {
        return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
      },
      // 注解3
      buttonDisabled() {
        return this.disabled || (this.elForm || {}).disabled;
      }
    },
    methods: {
      // 注解2
      handleClick(evt) {
        this.$emit('click', evt);
      }
    }
  };
</script>
1. 基础样式.el-button
image.png
2. 点击事件,$emit

这里这么做真的是太聪明了,通过传递回给父组件,与vue原来的@click事件名字又一样,做到了无感传递了!Vue中点击子组件触发父组件调用事件的流程如下:

// 父组件Parent.vue
<children @emitName="parentFunc"></children>
...
parentFunc(event) {
  console.log('点我干嘛');
}

// 子组件Children.vue
<button @click="handleClick">我是子组件的按钮</button>
...
handleClick(event) {
  this.$emit('emitName', event);
}
3.HTML <button> 标签的disabled属性
// 当buttonDisabled即按钮设置了不可点击,或者loading即设置了loading且loading为true时禁止点击按钮
 :disabled="buttonDisabled || loading"   

buttonDisabled详解:

buttonDisabled() {
  // this.disabled: 调用时设置的disabled,
  // (this.elForm || {}).disabled: 获取到父组件注入返回的对象或返回一个对象的函数(没注入就为{},为了避免报错吧)里的disabled属性
  return this.disabled || (this.elForm || {}).disabled;
}

Vue官方文档API的详解: inject

4. 动态class

这里用了第三种:class="[classA, { classB: isB, classC: isC }]"

<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
对应的就是红框里这几个参数,可去饿了么官方文档F12看具体样式
5. loading图标
image.png
image.png
6.icon
 // 有传入icon属性且没有loading的时候
<i :class="icon" v-if="icon && !loading"></i>
DOM结构为 search样式有定义
7. 默认插槽

如果有默认插槽则提供插槽位置:

<span v-if="$slots.default"><slot></slot></span>  // 注解7

关于插槽:

// 对于这样的情况,<slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>  // 这里!就为默认
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

相关文章

网友评论

    本文标题:深入Vue之解析ElementUI组件--button

    本文链接:https://www.haomeiwen.com/subject/tzfwuctx.html