当前位置:   article > 正文

element-plus 组件解析 - Layout 布局

element-plus


element-plus 相关,第1篇

layout 布局是由 row 和 col 组件组合,通过基础的 24 分栏,简单的实现布局。element-plus layout 组件

1,layout 布局简介

layout 布局默认使用 flex 布局,

  • row 组件作为 flex 容器。
  • col 组件作为 flex 元素。

最终编译结果

<div class="el-row">
  <div class="el-col"></div>
  <div class="el-col"></div>
</div>
  • 1
  • 2
  • 3
  • 4

2,row 组件

我们从 props 入手,一共有4个

  1. tag,自定义元素标签,默认 div。通过动态组件 component 实现。
<template>
  <component :is="tag" :class="rowKls" :style="style">
    <slot />
  </component>
</template>
  • 1
  • 2
  • 3
  • 4
  • 5
  1. gutter,栅格间隔,默认0px。表示栅格(也就是 col 组件)之间的间距。
    在这里插入图片描述

实现分2步:

  • 给 row 组件设置 marginRightmarginLeft
styles.marginRight = styles.marginLeft = `-${props.gutter / 2}px`
  • 1
  • 给每个 col 组件设置 paddingLeft paddingRight
styles.paddingLeft = styles.paddingRight = `${gutter.value / 2}px`
  • 1

这样 row 组件左边的 marginLeft 会被第一个col 组件的 paddingLeft 抵消。右边同理。

这样就实现了 col 组件的间隔。

  1. justify
  2. align

这2个是 flex 布局下,水平和垂直方向的对齐方式,不多介绍。

3,col 组件

我们还是从 props 入手,主要的一共有6个

  1. tag,自定义元素标签,不多赘述。
  2. span,占据的栅格数,默认24,也就是占满整行。0会设置 display:none
  3. offset,栅格左侧的间隔格数,默认0。通过设置 margin-left 实现。
  4. push,栅格向右移动格数,默认0,通过设置position:relative; left: x% 实现。
  5. pull,栅格向左移动格数,默认0,通过设置position:relative; right: x% 实现。

注意,push 和 pull 的实现中,移动的距离并不会影响相邻其他 col 组件的位置。这是有相对定位决定的。

元素相对定位,并不会脱离文档流。
也就是说,设置的 right 或 left 会使相对定位元素的位置发生变化。但其他的元素依然会按照相对定位元素的初始位置正常布局。

关键 scss 实现

math.div(1, 24)表示 1/24

@for $i from 0 through 24 {
  .el-col-#{$i} {
    max-width: (math.div(1, 24) * $i * 100) * 1%;
    flex: 0 0 (math.div(1, 24) * $i * 100) * 1%;
  }

  .el-col-offset-#{$i} {
    margin-left: (math.div(1, 24) * $i * 100) * 1%;
  }

  .el-col-pull-#{$i} {
    position: relative;
    right: (math.div(1, 24) * $i * 100) * 1%;
  }

  .el-col-push-#{$i} {
    position: relative;
    left: (math.div(1, 24) * $i * 100) * 1%;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

重点

1,设置占据栅格数的 css:el-col-xxx 时,使用了max-widthflex: 0 0 x%

  • max-width 用于指定最大宽度。
  • flex: 0 0 x% 设置 flex 元素 col 不能增大也不能缩小,宽度只能是 x%,也就是每个栅格的宽度都是定死的。

flex 元素的 width 优先级:max-width > flex-basic > width

2,百分比

max-width百分比,相对于其父级容器宽度
flex-basic百分比,相对于其父弹性容器主轴尺寸
margin-left百分比,相对于最近的块容器宽度
left百分比,相对于元素包含块的宽度。(el-row有设置相对定位哦)

所以可用百分比来表示,1 栅格的宽度 = el-row 宽度的1/24 = (math.div(1, 24) * 100) * 1%;

3.2,响应式布局

col 组件还有 xs sm md lg xl 这几个关于响应式的 props

<template>
  <el-row :gutter="10">
    <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1">
      <div class="grid-content ep-bg-purple"/>
    </el-col>
    <el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11">
      <div class="grid-content ep-bg-purple-light"/>
    </el-col>
  </el-row>
</template>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这几个可以传 number 或 object。关键处理逻辑:

const sizes = ['xs', 'sm', 'md', 'lg', 'xl']
sizes.forEach((size) => {
  if (isNumber(props[size])) {
    classes.push(`el-col-${size}-${props[size]}`) // el-col-xs-2
  } else if (isObject(props[size])) {
    // props[xs] = { span?: number, offset?: number, pull?: number, push?: number }
    Object.entries(props[size]).forEach(([prop, sizeProp]) => {
      classes.push(
        prop !== 'span'
          ? `el-col-${size}-${prop}-${sizeProp}` // el-col-xs-offset-2
          : `el-col-${size}-${sizeProp}` // el-col-xs-2
      )
    })
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

样式实现

$sm: 768px;
$md: 992px;
$lg: 1200px;
$xl: 1920px;

$breakpoints: (
  'xs': '(max-width: #{$sm})',
  'sm': '(min-width: #{$sm})',
  'md': '(min-width: #{$md})',
  'lg': '(min-width: #{$lg})',
  'xl': '(min-width: #{$xl})',
);

@mixin res($key, $map: $breakpoints) {
  @if map-has-key($map, $key) {
    @media only screen and #{unquote(map-get($map, $key))} {
      @content;
    }
  } @else {
    @warn "Undefined points: `#{$map}`";
  }
}

@mixin col-size($size) {
  @include res($size) {
    .el-col-#{$size}-0 {
      display: none;
    }
    @for $i from 0 through 24 {
      .el-col-#{$size}-#{$i} {
        @if $i != 0 {
          display: block;
        }
        max-width: (math.div(1, 24) * $i * 100) * 1%;
        flex: 0 0 (math.div(1, 24) * $i * 100) * 1%;
      }

      .el-col-#{$size}-offset-#{$i} {
        margin-left: (math.div(1, 24) * $i * 100) * 1%;
      }

      .el-col-#{$size}-pull-#{$i} {
        position: relative;
        right: (math.div(1, 24) * $i * 100) * 1%;
      }

      .el-col-#{$size}-push-#{$i} {
        position: relative;
        left: (math.div(1, 24) * $i * 100) * 1%;
      }
    }
  }
}

@include col-size(xs);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

以上。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/116834?site
推荐阅读
相关标签
  

闽ICP备14008679号