elementUI源码分析-03-container、butto

2021-02-03  本文已影响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,可以添加的内部提供的图标

上一篇 下一篇

猜你喜欢

热点阅读