美文网首页
elementUI源码分析-03-container、butto

elementUI源码分析-03-container、butto

作者: 范小饭_ | 来源:发表于2021-02-03 10:31 被阅读0次

    一、container布局容器

    用于布局的容器组件,方便快速搭建页面的基本结构。

    image.png

    <el-container>:外层容器。当子元素中包含 <el-header> 或 <el-footer>时,全部子元素会垂直上下排列,否则会水平左右排列。

    <el-header>:顶栏容器。

    <el-aside>: 侧边栏容器。

    <el-main>:主要区域容器。

    <el-footer>:底栏容器。

    <el-container> 的子元素只能是后四者,后四者的父元素也只能是 <el-container>

    也就是说,<el-container><el-header><el-aside><el-main><el-footer>只能是组合出道, 因为以上采用了flex 布局,也就是说这套组件就是使用了flex布局,是flex布局属性排列组合后的各种布局方式。

    el-container

    el-container这个组件只接受一个参数就是direction,用来描述子元素的排列方向.
    默认情况下,如果子元素中有el-header或el-footer时为竖向排列,其余情况下默认横向排列。

    源码如下

    <template>
      <section class="el-container" :class="{ 'is-vertical': isVertical }">
        <slot></slot>
      </section>
    </template>
    
    <script>
      export default {
        name: 'ElContainer',
        componentName: 'ElContainer',
        props: {
          direction: String
        },
        computed: {
          isVertical() {
            if (this.direction === 'vertical') {
              return true;
            } else if (this.direction === 'horizontal') {
              return false;
            }
            // 子元素中有 el-header 或 el-footer 时为 vertical,否则为 horizontal
            return this.$slots && this.$slots.default
              ? this.$slots.default.some(vnode => {
                const tag = vnode.componentOptions && vnode.componentOptions.tag;
                return tag === 'el-header' || tag === 'el-footer';
              })
              : false;
          }
        }
      };
    </script>
    
    

    默认的el-container容器有一个el-container类名,用来设置默认style样式

    .el-container {
        display: flex;
        flex-direction: row;
        flex: 1;
        flex-basis: auto;
        box-sizing: border-box;
        min-width: 0;
    }
    

    通过接收的direction的值,在结合computed的isVertical属性,判断是否给元素添加is-vertical的class类名。如果有,则用is-vertical的样式去覆盖el-container的子元素排放方式的样式。

    .el-container {
        display: flex;
        flex-direction: row;
        flex: 1;
        flex-basis: auto;
        box-sizing: border-box;
        min-width: 0;
    }
    .el-container.is-vertical {
        flex-direction: column;
    }
    

    el-header

    el-header组件,只接受一个height属性,用来添加style设置高度,默认为60px。

    源码如下

    <template>
      <header class="el-header" :style="{ height }">
        <slot></slot>
      </header>
    </template>
    
    <script>
      export default {
        name: 'ElHeader',
    
        componentName: 'ElHeader',
    
        props: {
          height: {
            type: String,
            default: '60px'
          }
        }
      };
    </script>
    

    el-header的默认样式

    .el-header{
        text-align: center;
        background-color: #b3c0d1;
        color: #333;
        line-height: 60px;
        box-sizing: border-box;
        flex-shrink: 0;
        padding: 0 20px;
    }
    

    el-aside

    el-aside只接收一个width组件,用来设置侧边栏的宽度,默认是300px

    <template>
      <aside class="el-aside" :style="{ width }">
        <slot></slot>
      </aside>
    </template>
    
    <script>
      export default {
        name: 'ElAside',
    
        componentName: 'ElAside',
    
        props: {
          width: {
            type: String,
            default: '300px'
          }
        }
      };
    </script>
    
    

    el-aside默认样式

    .el-aside{
        background-color: #d3dce6;
        text-align: center;
        line-height: 300px;
        color: #333;
        overflow: auto;
        box-sizing: border-box;
        flex-shrink: 0;
    }
    

    el-main

    el-main只是一个包括的容器

    <template>
      <main class="el-main">
        <slot></slot>
      </main>
    </template>
    
    <script>
      export default {
        name: 'ElMain',
        componentName: 'ElMain'
      };
    </script>
    
    

    el-main的默认样式

    .el-main{
        background-color: #e9eef3;
        color: #333;
        text-align: center;
        line-height: 160px;
        display: block;
        flex: 1;
        flex-basis: auto;
        padding: 20px;
        overflow: auto;
    }
    

    el-footer

    el-footer与el-hearder类似,只接收一个height属性,用来设置footer的高度。

    <template>
      <footer class="el-footer" :style="{ height }">
        <slot></slot>
      </footer>
    </template>
    
    <script>
      export default {
        name: 'ElFooter',
    
        componentName: 'ElFooter',
    
        props: {
          height: {
            type: String,
            default: '60px'
          }
        }
      };
    </script>
    
    

    el-footer的默认样式

    .el-footer{
        text-align: center;
        background-color: #b3c0d1;
        color: #333;
        line-height: 60px;
        padding: 0 20px;
        flex-shrink: 0;
        box-sizing: border-box;
    }
    

    二、button

    el-button实际上就是对原生button的再封装。


    button

    el-button组件的引用方式如下

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

    el-button的参数列表如下

    参数 说明 类型 可选值 默认值
    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

    再结合el-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的默认样式如下

    .el-button {
      display: inline-block;
      line-height: 1;
      white-space: nowrap;
      cursor: pointer;
      background: #fff;
      border: 1px solid #dcdfe6;
      color: #606266;
      -webkit-appearance: none;
      text-align: center;
      box-sizing: border-box;
      outline: none;
      margin: 0;
      transition: .1s;
      font-weight: 500;
      -moz-user-select: none;
      -webkit-user-select: none;
      -ms-user-select: none;
      padding: 12px 20px;
      font-size: 14px;
      border-radius: 4px;
    }
    

    display: inline-block; 表示其为内联元素,可横向排列
    white-space: nowrap; 表示文本不换行
    cursor: pointer; 鼠标滑过显示小手形状
    -webkit-appearance: none; 将按钮原始样式去掉
    line-height: 1; 行高等于字体大小

    type: 通过接受type值,来生成描述背景色等的lass名、比如type=primary, 即el-button--primary,用来设置按钮的背景色,字体颜色、边框颜色。

    .el-button--primary {
        color: #fff;
        background-color: #409eff;
        border-color: #409eff;
    }
    

    size: 通过设置size,来生成描述按钮大小的class名,比如size=small, 即el-button--small。

    .el-button--small {
        padding: 9px 15px;
        font-size: 12px;
        border-radius: 3px;
    }
    

    plain: 通过设置plain,用来生成描述对应type下的朴素样式的按钮、

    .button--primary.is-plain {
        color: #409eff;
        background: #ecf5ff;
        border-color: #b3d8ff;
    }
    

    round : 用来描述是否是圆角按钮,来生成对应描述圆角的class名,is-round

    .el-button.is-round {
        border-radius: 20px;
        padding: 12px 23px;
    }
    

    circle: 是否是原型按钮,来生成对应50%圆角的class名,is-circle

    .el-button.is-circle {
        border-radius: 50%;
        padding: 12px;
    }
    

    loading : 是否是加载中按钮,如果是加载中的按钮,则给元素添加el-icon-loading类,添加在加载的图标
    disabled : 是否是禁用状态,添加对应的类名is-disabled,并且给原生button设置disabled="disabled",使其不可点击

    .el-button.is-disabled{
      cursor: not-allowed;
    }
    <button disabled="disabled" type="button" class="el-button el-button--primary is-disabled"><!----><!----><span>主要按钮</span></button>
    

    icon: 通过设置icon,可以添加的内部提供的图标
    autofocus : 用来设置按钮是否聚焦,如果autofocus=true,则给原生button设置autofocus="autofocus"
    native-type : 用来设置原生button的type属性,用来描述按钮的类型,即button、reset、submit

    inject是跟表单相关的,等后面表单再说吧。

    三、buttonGroup

    按钮组

    buttonGroup
    <el-button-group>
      <el-button type="primary" icon="el-icon-arrow-left">上一页</el-button>
      <el-button type="primary">下一页<i class="el-icon-arrow-right el-icon--right"></i></el-button>
    </el-button-group>
    

    源码如下

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

    el-button-group就是用来嵌套一组el-button,并且相邻两个按钮内侧的圆角去掉,且有一条空白线相连。具体实现的style如下

    // 圆角设置
    .el-button-group{
      display: inline-block;
      vertical-align: middle;
    }
    .el-button-group>.el-button:not(:last-child) {
        margin-right: -1px;
    }
    .el-button-group>.el-button:first-child {
        border-top-right-radius: 0;
        border-bottom-right-radius: 0;
    }
    .el-button-group>.el-button:last-child {
        border-top-left-radius: 0;
        border-bottom-left-radius: 0;
    }
    .el-button-group>.el-button:not(:first-child):not(:last-child) {
        border-radius: 0;
    }
    // 空白线
    .el-button-group .el-button--primary:first-child {
        border-right-color: hsla(0,0%,100%,.5);
    }
    .el-button-group .el-button--primary:not(:first-child):not(:last-child) {
        border-left-color: hsla(0,0%,100%,.5);
        border-right-color: hsla(0,0%,100%,.5);
    }
    button-group .el-button--primary:last-child {
        border-left-color: hsla(0,0%,100%,.5);
    }
    

    其实就是运用选择器,将第一个按钮右侧圆角,最后一个按钮左侧圆角,以及中间按钮的全部圆角去掉,即形成了圆角设置,空白线也是类似处理。因为按钮默认都有border,颜色和按钮主体颜色一致,这里只是修改了border的颜色

    四、link

    文字超链接

    link
    <div>
      <el-link href="https://element.eleme.io" target="_blank">默认链接</el-link>
    </div>
    

    参数如下

    参数 说明 类型 可选值 默认值
    type 类型 string primary / success / warning / danger / info default
    underline 是否下划线 boolean true
    disabled 是否禁用状态 boolean false
    href 原生 href 属性 string
    icon 图标类名 string -

    el-link,其实是对原生a标签的封装。

    源码如下

    <template>
      <a
        :class="[
          'el-link',
          type ? `el-link--${type}` : '',
          disabled && 'is-disabled',
          underline && !disabled && 'is-underline'
        ]"
        :href="disabled ? null : href"
        v-bind="$attrs"
        @click="handleClick"
      >
    
        <i :class="icon" v-if="icon"></I>
    
        <span v-if="$slots.default" class="el-link--inner">
          <slot></slot>
        </span>
    
        <template v-if="$slots.icon"><slot v-if="$slots.icon" name="icon"></slot></template>
      </a>
    </template>
    
    <script>
    
    export default {
      name: 'ElLink',
    
      props: {
        type: {
          type: String,
          default: 'default'
        },
        underline: {
          type: Boolean,
          default: true
        },
        disabled: Boolean,
        href: String,
        icon: String
      },
    
      methods: {
        handleClick(event) {
          if (!this.disabled) {
            if (!this.href) {
              this.$emit('click', event);
            }
          }
        }
      }
    };
    </script>
    

    el-link的默认样式如下

    .el-link {
        display: inline-flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        vertical-align: middle;
        position: relative;
        text-decoration: none;
        outline: none;
        cursor: pointer;
        padding: 0;
        font-size: 14px;
        font-weight: 500;
    }
    

    type : 通过设置type,添加对应的class类,给a标签设置对应的字体颜色

    .el-link.el-link--primary {
        color: #409eff;
    }
    

    underline : 是否有下滑线,如果添加,那么在hover的时候,会添加一个after伪类来创建下划线

    .el-link.is-underline:hover:after {
        content: "";
        position: absolute;
        left: 0;
        right: 0;
        height: 0;
        bottom: 0;
        border-bottom: 1px solid #409eff;
    }
    .el-link.el-link--default:after {
        border-color: #409eff;
    }
    

    disabled: 是否是禁用状态,如果设置了,会根据对应type,设置对应样式

    .el-link.el-link--danger {
        color: #f56c6c;
    }
    .el-link.el-link--danger.is-disabled {
        color: #fab6b6;
    }
    

    href : 即设置原生a标签的href属性
    icon: 通过设置icon,可以添加的内部提供的图标

    相关文章

      网友评论

          本文标题:elementUI源码分析-03-container、butto

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