element-plus 组件解析 - Layout 布局


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>

2,row 组件

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

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

实现分2步:

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

这样 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,设置占据栅格数的 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>

这几个可以传 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
      )
    })
  }
})

样式实现

$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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雪天的夏风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值