Element源码分析系列3-Button(按钮)

栏目: 编程工具 · 发布时间: 6年前

内容简介:Button(按钮)可能是最简单的一个组件了(Icon组件表示不服,我TM连点击事件都没),因为Button涉及到的东西真的不多,无非就是响应点击事件和具体的样式编写,最多加一个loading状态禁止点击,下图是Element的Button示意图,官网代码主要就分为直角,圆角,圆形按钮这几种,这里的按钮颜色看着很舒服,比如危险按钮的颜色不是#ff0000,而是有一点淡的红色,视觉效果更柔和,可以借鉴这些颜色直接上代码,代码量不多

Button(按钮)可能是最简单的一个组件了(Icon组件表示不服,我TM连点击事件都没),因为Button涉及到的东西真的不多,无非就是响应点击事件和具体的样式编写,最多加一个loading状态禁止点击,下图是Element的Button示意图,官网代码 点此

Element源码分析系列3-Button(按钮)

主要就分为直角,圆角,圆形按钮这几种,这里的按钮颜色看着很舒服,比如危险按钮的颜色不是#ff0000,而是有一点淡的红色,视觉效果更柔和,可以借鉴这些颜色

Button源码分析

直接上代码,代码量不多

<template>
  <button
    class="el-button"
    @click="handleClick"
    :disabled="buttonDisabled || loading"
    :autofocus="autofocus"
    :type="nativeType"
    :class="[
      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>
    <i :class="icon" v-if="icon && !loading"></i>
    <span v-if="$slots.default"><slot></slot></span>
  </button>
</template>
<script>
  export default {
    name: 'ElButton',
    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;
      },
      buttonDisabled() {
        return this.disabled || (this.elForm || {}).disabled;
      }
    },
    methods: {
      handleClick(evt) {
        this.$emit('click', evt);
      }
    }
  };
</script>
复制代码

我们一步步分析,首先很明确, <el-button> 就是封装了原生的button而已,原生button有个地方需要注意,请始终为 <button> 元素规定 type 属性。不同的浏览器对 <button> 元素的 type 属性使用不同的默认值,值有3种, button , submit , reset 分别表示按钮,提交,重置。而且如果在 HTML 表单中使用 <button> 元素,不同的浏览器可能会提交不同的按钮值。请使用 <input> 在 HTML 表单中创建按钮

首先我们来看第一句 class="el-button" ,这里声明了按钮的基本类,也就是所有按钮通用的样式,见下图

Element源码分析系列3-Button(按钮)

可以看到其中有几个样式比较重要,首先是 display:inline-block ,表明按钮内联块状分布,一行可以有多个排列,且可以控制宽高, -webkit-appearence:none 表示将按钮原生的样式去掉,首先是太丑其实不同浏览器表现不同,注意这里的按钮没有设置宽高,宽高都是由字体大小撑开来的,然后设置 padding 来产生内间距, line-height:1 表示行高和字体大小一样

然后第二句 @click="handleClick" 这个是重点,这表明给原生button绑定了点击事件,我们使用该组件时是按下图的方式

Element源码分析系列3-Button(按钮)
这里需要手动写一个 @click ,然后我们看一下 handleClick

的代码

methods: {
      handleClick(evt) {
        this.$emit('click', evt);
      }
}
复制代码

这里实际上是用Vue的内置事件系统向父级触发了一个click事件,父级就是 <el-button> ,因为实际点击我们是点击在原生button上的,而使用组件时却是在 <el-button> 上监听事件,所以这里需要将click事件派发到父级,父级监听这个click事件,第二个参数是事件对象。如果不写这个 handleClick 将不会触发任何点击效果

第三句 :disabled="buttonDisabled || loading" 表示控制按钮的禁用状态,注意disabled是原生的属性,当其为true时,按钮无法被点击,且鼠标hover的样式不是小手,这里禁用状态是由loading状态和用户自定义的禁用与否共同决定,其中用户定义的disabled会被转化为一个计算属性,如下,后面的项表示表单相关的内容,此处不详细解释

禁用状态是由2部分组成:一是功能禁用,通过原生的disabled属性来实现,二是样式上禁用,通过将按钮置灰和 cursor:not-alowed 将鼠标展示为一个禁止的标志来实现

buttonDisabled() {
        return this.disabled || (this.elForm || {}).disabled;
 }
复制代码

再来看 :autofocus="autofocus" 这句话,如果为true表示按钮自动获得焦点,按钮获得焦点就是按钮为focus的状态,可以用于提示用户

:type="nativeType" 表示按钮的原生类型,button ,reset还是submit,接下来是控制按钮不同种类的class

:class="[
      type ? 'el-button--' + type : '',
      buttonSize ? 'el-button--' + buttonSize : '',
      {
        'is-disabled': buttonDisabled,
        'is-loading': loading,
        'is-plain': plain,
        'is-round': round,
        'is-circle': circle
      }
    ]"
复制代码

这里注意绑定的class是一个数组,里面又混合了对象的形式,这种写法可以借鉴,对象里面的类控制了该按钮是否是禁用,loading,朴素,圆角,圆形,然后是这3句话

<i class="el-icon-loading" v-if="loading"></i>
<i :class="icon" v-if="icon && !loading"></i>
<span v-if="$slots.default"><slot></slot></span>
复制代码

这3句就是 <button></button> 中间的内容了,第一个i标签表示加载状态下的loading图案,可以看出这个图案就是一个字体图标而已,在不断的旋转( animation:rotating 2s linear infinite )

Element源码分析系列3-Button(按钮)
Element源码分析系列3-Button(按钮)

第二个i标签是按钮的图标,用户设置,此图标在loading状态下隐藏,然后是 <span> 这个标签当且仅当 <el-button> 中有内容时才存在,内容放在slot插槽中, $slots.default 来判断是否有子元素存在,可以借鉴

后面的 inject 估计是和表单相关,这里不做介绍,注意一下当按钮被点击时,样式也会发生变化,下图中成功按钮被点击变成深色,这是通过css的 :active 伪类来实现,我之前一直以为只有a标签有active伪类,原来button也可以用啊

Element源码分析系列3-Button(按钮)

下面讲讲按钮的大小控制,其实很简单,

Element源码分析系列3-Button(按钮)
size属性在通过绑定class的这句话 buttonSize ? 'el-button--' + buttonSize : '' 将size转化为类名,从而使用不同的尺寸类来控制大小, buttonSize

是个计算属性通过size得到

综上,我们明白了组件的各种属性最终会转化为对应的class来控制按钮的样式表现,就是在:class里拼接字符串而已

ButtonGroup源码分析

ButtonGroup就是按钮组,将多个按钮组合在一起,如下图

Element源码分析系列3-Button(按钮)
其源码就更简单了,就是封装了一个div,注意 el-button-group 的内容是 display:inline-block

,也就说明这个wrapper其实也是内联块状的表现,里面的slot承载子button

<template>
  <div class="el-button-group">
    <slot></slot>
  </div>
</template>
<script>
  export default {
    name: 'ElButtonGroup'
  };
</script>
复制代码

这里重点在按钮之间的白色间隙是怎么实现的,答案就是css伪类 :last-child:first-child:not:first-child 选择器用于选取 属于其父元素的首个子元素的指定选择器 ,也就是说如果多个相同层级的p标签排在一起,他们的父元素是div,那么p:first-child就会选中第一个p标签

下面上scss代码

@each $type in (primary, success, warning, danger, info) {
    .el-button--#{$type} {
      &:first-child {
        border-right-color: rgba($--color-white, 0.5);
      }
      &:last-child {
        border-left-color: rgba($--color-white, 0.5);
      }
      &:not(:first-child):not(:last-child) {
        border-left-color: rgba($--color-white, 0.5);
        border-right-color: rgba($--color-white, 0.5);
      }
    }
  }
复制代码

很明显,这里设置了第一个元素的右侧border和最后一个的左侧border,对于既不是第一个也不是最后一个的元素,设置双侧border,注意这里只设置了border的颜色,其实所有按钮默认都有border,颜色和按钮主体颜色一致,所以这里只修改了颜色就能达到目的


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C语言算法速查手册

C语言算法速查手册

程晓旭、耿鲁静、张海、王勇 / 2009-10 / 49.00元

《C语言算法速查手册》用C语言编写了科研和工程中最常用的166个算法,这些算法包括复数运算、多项式的计算、矩阵运算、线性代数方程组的求解、非线性方程与方程组的求解、代数插值法、数值积分法、常微分方程(组)初值问题的求解、拟合与逼近、特殊函数、极值问题、随机数产生与统计描述、查找、排序、数学变换与滤波等。同时结合这些算法列举了将近100个应用实例,对其进行验证和分析。 《C语言算法速查手册》适......一起来看看 《C语言算法速查手册》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试