element-ui 组件库 button 源码分析

这篇具有很好参考价值的文章主要介绍了element-ui 组件库 button 源码分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

团队要根据新的 UI 规范实现一个组件库,button 组件规范要支持多种主题换肤,字体颜色、背景颜色、边框和禁用使用新的规范,并且一种主题颜色主要组件上使用两种主题颜色混合。另外,增加多一种幽灵按钮类型,经过分析,在 element-ui 的 button 组件上改造麻烦,不好维护,所以需要造一个 button 组件,阅读 element-ui 组件库 button 的源码设计,参考 element-plus css 自定义变量 实现

element-ui 源码分析 button

button 属性

button文档属性 可以定义按钮的尺寸(size),类型(type),朴素样式(plain),圆角(round),圆形(circle),加载(loading),禁用(disabled),图标(icon),是否聚焦(autofocus)等

参数 说明 类型 可选值 默认值
size 尺寸 string medium / small / mini
type 类型 string primary / success / warning / danger / info / text
plain 是否朴素按钮 boolean false
round 是否圆角按钮 boolean false
circle 是否圆形按钮 boolean false
loading 是否加载中状态 boolean false
disabled 是否禁用状态 boolean false
icon 图标类名 string
autofocus 是否默认聚焦 boolean false
native-type 原生 type 属性 string button / submit / reset button

button 使用

<template>
  <div>
    <el-button>默认按钮</el-button>

    <!-- 尺寸(size):medium(中等),small(小型),mini(超小) -->
    <el-button size="medium">中等按钮</el-button>

    <!-- 类型(type):default(默认),primary(主要),success(成功),info(信息),warning(警告),danger(危险),text(文本) -->
    <el-button type="primary">主要按钮</el-button>
    <el-button type="text">文字按钮</el-button>

    <!-- 朴素(plain):true,false -->
    <el-button type="primary" plain>主要按钮</el-button>

    <!-- 圆角(round):true,false -->
    <el-button round>主要按钮</el-button>

    <!-- 圆形(circle):true,false。一般与图标 icon 连用 -->
    <el-button icon="el-icon-search" circle></el-button>

    <!-- 禁用(disabled):true,false。按钮颜色变浅,鼠标悬浮出现禁止符号。 -->
    <el-button disabled>禁用按钮</el-button>

    <!-- 图标(icon):设置icon属性即可,可以参考 icon 组件。设置在文字右边的 icon ,需要使用i标签,此时最好添加上 el-icon--right 类。 -->
    <el-button type="primary" icon="el-icon-edit">图标按钮</el-button>
    <el-button type="primary"
      >图标按钮<i class="el-icon-edit el-icon--right"></i
    ></el-button>

    <!-- 加载(loading):true,false。为 true 时点击事件失效。 -->
    <el-button type="primary" :loading="true">加载中</el-button>
  </div>
</template>

Button 源码分析

相关文件路径:

  • packages/button/src/button.vue button vue 单文件组件
  • packages/theme-chalk/src/common/var.scss#L506-L591 按钮 SCSS 变量名文件
  • packages/theme-chalk/button.scss 按钮样式文件
  • packages/theme-chalk/mixins/_button.scss 按钮混入样式文件,公共混入代码,例如按钮不同 type 样式、按钮plain朴素样式、按钮size大小样式
  • packages/theme-chalk/minxins.scss 混入样式文件, 包括 bem 规范、when状态 mixin 代码片段,例如 b(button) 会转化为 el-button
button.vue 文件

button.vue文件路径

props 的属性在文档说明中都有提到,是对组件的扩展

  • type: 拼接在 el-button-- 后面,生成不同的 class 类,重新定义 colorbackground-colorborder-color 覆盖 el-button 默认样式
  • size:外部控制按钮大小,同时可以被表单元素和全局控制,el-button-- + size 类样式,例如 el-button--small
  • icon:支持不同的图标,加载中的图标只能使用 el-icon-loading
  • nativeType:按钮的原生类型,默认是 button,可以是 submitreset
  • loading:加载中的状态,is-loading 样式,按钮会被禁用
  • disabled:禁用按钮,is-disabled 类样式,使用 when(disabled) 生成
  • plain:朴素按钮,is-plain类样式
  • autofocus:自动聚焦,focus 状态样式按钮
  • round:圆角样式 is-round
  • circle:圆心样式 is-circle,一般配合 icon 图标使用
// button.vue 源码

<template>
  <!-- 原生的 button 进行样式封装。 -->
  <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
      }
    ]"
  >
    <!-- 
      1. el-icon-loading 是加载图标类,
      2. 这里使用了两个 <i></i> 都是用来放图标的,会根据 loading 的值进行二选一
         并且 loading = ture 加载状态无法使用其他图标,同时外层 button 被设置为 disabled
    -->
    <i class="el-icon-loading" v-if="loading"></i>
    <i :class="icon" v-if="icon && !loading"></i>

    <!-- 按钮文本插槽,default 属性包括了所有没有被包含在具名插槽中的节点 -->
    <span v-if="$slots.default"><slot></slot></span>
  </button>
</template>
SCSS 变量文件

common/var.scss 公共变量文件源码 定义公共样式和所有组件样式变量的文件,例如主题颜色、字体颜色、字体大小等,可以通过这个文件实现组件库的换肤

例如主题变量 $--color-primary

mix 函数是将两种颜色按不同的占比混合生成一个新的颜色,例如 mix($--color-white, $--color-primary, 10%), $--color-white 颜色占比 10%,$--color-primary 占比 90%,生成一种新的颜色

$--color-primary: #409EFF !default;
/// color|1|Background Color|4
$--color-white: #FFFFFF !default;
/// color|1|Background Color|4
$--color-black: #000000 !default;
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; 
BEM CSS规范

element 的样式规范是使用 bem 管理,根据规范生成类名,避免样式污染,bem 函数的公共代码片段定义在 packages/theme-chalk/src/mixins/mixins.scss 文件

theme-chalk/src/mixins/config.scss 定义命名空间

$namespace: 'el';
$element-separator: '__';
$modifier-separator: '--';
$state-prefix: 'is-';

1、bblock 的 mixin简写函数,调用 @include b(button) 参数 $block 赋值 button, 拼接命名空间变量 $namespace el 得到 el-button, !global 改为全局变量,可以给下文使用, @content 占位符插入内容

@mixin b($block) {
  $B: $namespace+'-'+$block !global;

  .#{$B} {
    @content;
  }
}

使用 @mixin b 代码片段

@include b(button) {
  display: inline-block;
  line-height: 1;
}

编译结果是

.el-button {
  display: inline-block;
  line-height: 1;
}

2、e 是 element 的简写函数,@include e(icon) 调用,$element 传入 icon,在上面 b 函数已经将 $B 赋值为全局变量 el-button$currentSelector 拼接后得到 .el-button__icon,@at-root 是跳出嵌套,和 .el-button 同级,而不是 .el-button .el-button-icon 拼接在后面

@mixin e($element) {
  $E: $element !global;
  $selector: &;
  $currentSelector: "";
  @each $unit in $element {
    $currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
  }

  @if hitAllSpecialNestRule($selector) {
    @at-root {
      #{$selector} {
        #{$currentSelector} {
          @content;
        }
      }
    }
  } @else {
    @at-root {
      #{$currentSelector} {
        @content;
      }
    }
  }
}

3、m 修饰符函数,传入 primary, 遍历 $modifier 只有一个元素,遍历结果后 $currentSelector 赋值是 &--primary,在scss 编译, & 是上级类 el-button,编辑是 el-button--primary

@mixin m($modifier) {
  $selector: &;
  $currentSelector: "";
  @each $unit in $modifier {
    $currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
  }

  @at-root {
    #{$currentSelector} {
      @content;
    }
  }
}

使用 m 函数

@include b(button) {
  @include m(primary) {
  
  }
}

编译结果是

.el-button--primary {
  
}
button.scss 组件样式

组件库的样式单独单独放在一个目录管理,通过 gulp 打包,源码路径 packages/theme-chalk/src/button.scss

@include b(button) 定义 el-button 类样式,& + & 相邻两个按钮左间距 10pxbutton-size 是生成按钮的大小,设计水平、垂直的内边距,字体大小和边框圆角,抽象出方法定义在 packages/theme-chalk/src/mixins/_button

@include b(button) {
  // 基本样式,默认样式,在未指定 type 之前
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: $--button-default-background-color;	// 默认背景色, white
  border: $--border-base;	// 1px solid #DCDFE6
  border-color: $--button-default-border-color;		// #DCDFE6
  color: $--button-default-font-color;	// #606266
  -webkit-appearance: none;
  text-align: center;
  box-sizing: border-box;
  outline: none;
  margin: 0;
  transition: .1s;
  font-weight: $--button-font-weight;	// 500

  // 在 packages/theme-chalk/src/mixins/utils ,主要是 moz,webkit,ms 的用户选择设置
  @include utils-user-select(none);

  // 兄弟节点之间
  & + & {
    margin-left: 10px;
  }

  // 在 packages/theme-chalk/src/mixins/_button,设置按钮边距、字体、边框弧度
  @include button-size($--button-padding-vertical, $--button-padding-horizontal, $--button-font-size, $--button-border-radius);

  // 悬浮、聚焦按钮样式
  &:hover,
  &:focus {
    color: $--color-primary;
    border-color: $--color-primary-light-7;
    background-color: $--color-primary-light-9;
  }

  &::-moz-focus-inner {
    border: 0;
  }

  // 按钮图标和文字的间距
  & [class*="el-icon-"] {
    & + span {
      margin-left: 5px;
    }
  }
  ...
}

element-ui 组件库 button 源码分析

when 函数 是定义不同状态的样式,$state-prefixis-,传入状态类型拼接,例如 when(loading).el-button.is-loading

@mixin when($state) {
  @at-root {
    &.#{$state-prefix + $state} {
      @content;
    }
  }
}

when(plain)when(active)when(disabled)when(loading)when(round)when(circle) 分别定义 is-plainis-activeis-disabledis-loadingis-roundis-circle,这也是 button prop 传入的属性,生成不同的类样式显示

@include when(plain) {
    &:hover,
    &:focus {
      background: $--color-white;
      border-color: $--color-primary;
      color: $--color-primary;
    }

    &:active {
      background: $--color-white;
      border-color: mix($--color-black, $--color-primary, $--button-active-shade-percent);
      color: mix($--color-black, $--color-primary, $--button-active-shade-percent);
      outline: none;
    }
  }

  @include when(active) {
    color: mix($--color-black, $--color-primary, $--button-active-shade-percent);
    border-color: mix($--color-black, $--color-primary, $--button-active-shade-percent);
  }

  @include when(disabled) {
    &,
    &:hover,
    &:focus {
      color: $--button-disabled-font-color;
      cursor: not-allowed;
      background-image: none;
      background-color: $--button-disabled-background-color;
      border-color: $--button-disabled-border-color;
    }

    &.el-button--text {
      background-color: transparent;
    }

    &.is-plain {
      &,
      &:hover,
      &:focus {
        background-color: $--color-white;
        border-color: $--button-disabled-border-color;
        color: $--button-disabled-font-color;
      }
    }
  }

  @include when(loading) {
    position: relative;
    pointer-events: none;

    &:before {
      pointer-events: none;
      content: '';
      position: absolute;
      left: -1px;
      top: -1px;
      right: -1px;
      bottom: -1px;
      border-radius: inherit;
      background-color: rgba(255,255,255,.35);
    }
  }
  @include when(round) {
    border-radius: 20px;
    padding: 12px 23px;
  }
  @include when(circle) {
    border-radius: 50%;
    padding: $--button-padding-vertical;
  }

例如 is-plain 样式

element-ui 组件库 button 源码分析

组件传入 type,是通过下面 m() 函数定义不同的 class,button-variant 代码片段是定义在 mixins/_button,

@include m(primary) {
    @include button-variant($--button-primary-font-color, $--button-primary-background-color, $--button-primary-border-color);
  }
  @include m(success) {
    @include button-variant($--button-success-font-color, $--button-success-background-color, $--button-success-border-color);
  }
  @include m(warning) {
    @include button-variant($--button-warning-font-color, $--button-warning-background-color, $--button-warning-border-color);
  }
  @include m(danger) {
    @include button-variant($--button-danger-font-color, $--button-danger-background-color, $--button-danger-border-color);
  }
  @include m(info) {
    @include button-variant($--button-info-font-color, $--button-info-background-color, $--button-info-border-color);
  }

element-ui 组件库 button 源码分析

button-variant 传入不同的 colorbackground-colorborder-color 变量覆盖 default 默认按钮的字体颜色、背景颜色和边框颜色,并且定义了伪类 hoverfocusactivedisabled 交互状态,颜色变浅通过 mix白色 混合

@mixin button-variant($color, $background-color, $border-color) {
  color: $color;
  background-color: $background-color;
  border-color: $border-color;

  &:hover,
  &:focus {
    background: mix($--color-white, $background-color, $--button-hover-tint-percent);
    border-color: mix($--color-white, $border-color, $--button-hover-tint-percent);
    color: $color;
  }
  
  &:active {
    background: mix($--color-black, $background-color, $--button-active-shade-percent);
    border-color: mix($--color-black, $border-color, $--button-active-shade-percent);
    color: $color;
    outline: none;
  }

  &.is-active {
    background: mix($--color-black, $background-color, $--button-active-shade-percent);
    border-color: mix($--color-black, $border-color, $--button-active-shade-percent);
    color: $color;
  }

  &.is-disabled {
    &,
    &:hover,
    &:focus,
    &:active {
      color: $--color-white;
      background-color: mix($background-color, $--color-white);
      border-color: mix($border-color, $--color-white);
    }
  }

  &.is-plain {
    @include button-plain($background-color);
  }
}

&.is-plain 类覆盖主要按钮的颜色得到朴素按钮,使用 button-plain($background-color) 定义在同一个文件,伪类也是定义 colorbackground-colorborder-color 覆盖

@mixin button-plain($color) {
  color: $color;
  background: mix($--color-white, $color, 90%);
  border-color: mix($--color-white, $color, 60%);

  &:hover,
  &:focus {
    background: $color;
    border-color: $color;
    color: $--color-white;
  }

  &:active {
    background: mix($--color-black, $color, $--button-active-shade-percent);
    border-color: mix($--color-black, $color, $--button-active-shade-percent);
    color: $--color-white;
    outline: none;
  }

  &.is-disabled {
    &,
    &:hover,
    &:focus,
    &:active {
      color: mix($--color-white, $color, 40%);
      background-color: mix($--color-white, $color, 90%);
      border-color: mix($--color-white, $color, 80%);
    }
  }
}

element-ui 组件库 button 源码分析

button 提供 4 种按钮大小,默认是最大的按钮,还有 medium 中等、small 小的和 mini 特小的,它是调用 button-size 传入不同的垂直、水平的内间距、字体大小和边框圆角变量值,定义按钮的大小

  @include m(medium) {
    @include button-size($--button-medium-padding-vertical, $--button-medium-padding-horizontal, $--button-medium-font-size, $--button-medium-border-radius);
    @include when(circle) {
      padding: $--button-medium-padding-vertical;
    }
  }
  @include m(small) {
    @include button-size($--button-small-padding-vertical, $--button-small-padding-horizontal, $--button-small-font-size, $--button-small-border-radius);
    @include when(circle) {
      padding: $--button-small-padding-vertical;
    }
  }
  @include m(mini) {
    @include button-size($--button-mini-padding-vertical, $--button-mini-padding-horizontal, $--button-mini-font-size, $--button-mini-border-radius);
    @include when(circle) {
      padding: $--button-mini-padding-vertical;
    }
  }

element-ui 组件库 button 源码分析

button-size 代码定义在 mixin/_button.scss

@mixin button-size($padding-vertical, $padding-horizontal, $font-size, $border-radius) {
  padding: $padding-vertical $padding-horizontal;
  font-size: $font-size;
  border-radius: $border-radius;
  &.is-round {
    padding: $padding-vertical $padding-horizontal;
  }
}

按钮支持文本类型 el-button--text,将 borderbackground 变透明,设置不同的字体颜色,定义伪类状态

  @include m(text) {
    border-color: transparent;
    color: $--color-primary;
    background: transparent;
    padding-left: 0;
    padding-right: 0;

    &:hover,
    &:focus {
      color: mix($--color-white, $--color-primary, $--button-hover-tint-percent);
      border-color: transparent;
      background-color: transparent;
    }
    &:active {
      color: mix($--color-black, $--color-primary, $--button-active-shade-percent);
      border-color: transparent;
      background-color: transparent;
    }

    &.is-disabled,
    &.is-disabled:hover,
    &.is-disabled:focus {
      border-color: transparent;
    }
  }
}

总结一下,button 按钮的样式变量定义在 commont/var.scss 维护,其他组件也是这种做法,这样就做到只需要修改 var.scss 文件就可以实现组件库的换肤。

按钮的样式规范使用 bem 规范,@include b(button) 定义基础类样式 el-button;按钮大小是通过 @include button-size(...) 传入内边距、字体大小变量控制显示。

不同的按钮 type 类型、伪类状态还有朴素按钮,通过修改 colorbackground-colorborder-color 覆盖默认样式,颜色变浅通过 mix 函数混合白色生成新的颜色,文本按钮、按钮组还有不同的按钮状态根据 bem 规范生成类样式定义。

通过学习优秀的组件库设计,发现处处设计的很巧妙,站在巨人的肩膀上学习。文章来源地址https://www.toymoban.com/news/detail-402489.html

到了这里,关于element-ui 组件库 button 源码分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • element-ui消息组件

    目录 一、elementUI的消息组件 1、MessageBox 弹框:是模态框 2、Message 消息提示:非模态框,常用于主动操作后的反馈提示。 3、Notification 通知 二、Form表单: 1、基本结构  2、表单控件 三、Dialog组件 1、使用方法 1、MessageBox 弹框:是模态框 ​ (1)消息提示:当用户进行操作时

    2024年02月02日
    浏览(78)
  • element-ui图像组件、上传组件、分页组件

    el-image:保留了原生的img的属性 1、导航方向:通过mode属性设置 2、菜单项 示例: (1)使用elementUI的上传组件将图片上传到服务器并保存到数据库中 (2)在el-table控件中将上传的图片显示出来 实现过程: (1)给数据库中的数据表增加一列(image_url):保存图片在服务器中

    2024年02月07日
    浏览(34)
  • Element-UI组件使用 --踩坑篇

    问题描述 : Element ui 中的 el-input ,当 input 仅有一项时,使用 @keyup.enter.native 事件绑定回车事 件,点击回车之后浏览器会刷新页面 问题原因 :由于当表单只有一个文本框时,按下回车将会触发表单的提交事件,导致页面的刷新 解决方法1 :在 el-form 加上 @submit.native.prevent ,

    2024年02月04日
    浏览(28)
  • 【Vue框架】Vue2中element-ui/mint-ui组件库——element-ui引入组件以及使用案例、mint-ui引入组件及使用案例

    element-ui 提供了大量的组件,如:布局组件、表单组件、JS组件等等。 Element-ui官网: https://element.eleme.cn/#/zh-CN 安装 Element-ui: npm i element-ui -S 1.1.1 引入组件 引入 Element 完整引入(在 main.js 中写入以下内容): 按需引入 借助 babel-plugin-component,我们可以只引入需要的组件,以达到

    2024年02月07日
    浏览(42)
  • 修改element-ui源码

    element-ui修改源码 1.首先,从git上拉取element的源码 2.安装依赖 npm install 3.修改 packages 中的源码,然后进行打包 npm run dist 4.找到你的项目中的 node_modules 包下的 element-ui 文件夹下的 lib 包,用你修改好后打包生成的 lib 包进行替换即可生效 下载链接在官网底部

    2024年02月11日
    浏览(31)
  • 解决idea无法识别element-ui组件

    现象: 在创建一个新的web项目时,引入了element-ui组件, package.json中相关配置如图 然而在vue的开发中,却无法识别element-ui的组件,具体表现为:无法自动补全,黄色warning提示,未知HTML标记。 不过,虽然这么标记了但是页面运行没有任何问题。功能也都正常。 解决方法:

    2024年02月02日
    浏览(27)
  • element-ui upload图片上传组件使用

    图片上传前端收集 数据 再调用接口发送到后端 组件标签内的参数: 参数 说明 类型 可选值 默认值 action 必选参数,上传的地址 string — — headers 设置上传的请求头部 object — — multiple 是否支持多选文件 boolean — — data 上传时附带的额外参数 object — — name 上传的文件字段

    2023年04月19日
    浏览(31)
  • element-ui分析

    bootstrap 引导安装包 引导安装包 build:file 生成入口文件 node build/bin/iconInit.js 用于生成../../examples/icon.json,解析icon.scss, 把所有的icon的名字放在icon.json里面,遍历名字显示icon(不用每次添加了icon就要修改example) node build/bin/build-entry.js 主要用于生成 /src/index.js入口文件. node build/bi

    2024年02月10日
    浏览(24)
  • vue element-ui表格组件动态多级表头

    实际项目的需求,需要根据后端动态获取的方式来初始化表格的表头包含哪些信息,且有很多信息是有规律的,所以我们需要Element UI动态生成多级表头。需要的效果图如下: 由于统计维度是可变化的(它可以是省市也可以是区县),所以需要专门设置一个表格的数据来保存

    2024年02月10日
    浏览(41)
  • Vue2 - 引入Element-UI组件样式

    官方文档 https://element.eleme.cn/#/zh-CN/component/installation 推荐使用 npm 的方式安装 ,它能更好地和 webpack 打包工具配合使用。 在终端cd到项目文件夹下安装 也可以通过CDN(不推荐) 目前可以通过 unpkg.com/element-ui 获取到最新版本的资源,在页面上引入 js 和 css 文件即可开始使用。

    2024年02月06日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包