3.13 Layout 布局

0x00 简介

组件提供了布局的栅格化(Grid Layout)系统,通过基础的 24 分栏,迅速简便地创建布局。该系统使用RowCol 栅格组件进行创建。本文将深入分析源码,剖析其实现原理,耐心读完,相信会对您有所帮助。

🔗 组件文档 Layout 🔗 gitee 源码 行组件 row.js 🔗 gitee 源码 列组件 col.js

更多组件剖析详见 👉 📚 Element 2 源码剖析组件总览

0x01 Grid Layout

栅格化提高了页面布局的一致性跟复用性,提升了整个设计开发流程的效率。同时使得网页的布局更加规范和简洁,提升用户体验。

网页栅格化神器 Grid.Guide ,可以自由设置最大宽度、列数以及留白边界自动动生成多种最佳栅格方案以供选择。

image.png

Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多 12 列。

element 2 采用 Ant Design 的设计理念:在 12 栅格系统的基础上,将整个设计建议区域按照 24 等分的原则进行划分,解决在设计区域内大量信息收纳的问题。


栅格化布局系统 通过一系列的行(row)和列(col)来定义信息区块的外部框架,以保证页面的每个区域能够稳健地排布起来。下面就介绍一下栅格系统的工作原理:

  • 通过 row 在水平方向建立一组 column(简写 col)。

  • 内容应当放置于 col 内,并且只有 col 可以作为 row 的直接元素。

  • 栅格系统中的列是指 1 到 24 的值来表示其跨越的范围。例如,三个等宽的列可以使用 <col :span="8" /> 来创建。

  • 如果一个 row 中的 col 总和超过 24,那么多余的 col 会作为一个整体另起一行排列。

接下来对组件行(row)和列(col)一一进行讲解。

0x02 Row 行组件

packages/row/src/row.js 使用渲染函数构建组件,支持组件渲染成自定义元素标签,主要用来作为col的容器。

render()

组件根据指定自定义元素渲染标签节点,由组件 prop 属性值动态计算添加 class 和 自定义样式(计算属性style),内部提供一个匿名插槽用于分发内容。

JSX 语法中,h 作为 createElement 的别名。第二个参数是一个包含模板相关属性的数据对象VNodeData,对象属性如下。

若自定义元素标签为<div>,等同于如下 template 实现。

组件 props

组件定义了 5 个 prop : tagguttertypejustifyalign

tag

支持组件渲染成自定义 html 标签,默认值为 div, 作为 createElement 方法的第一个参数。

gutter

栅格间隔设置,用来指定每一栏之间的间隔,默认间隔为 0。col 组件通过获取父组件rowgutter 计算自己的左右 padding 。

Flex 布局设置

type 设置布局模式,可选 flex,仅在现代浏览器下有效。

type 值为flex{ 'el-row--flex': type === 'flex' } 会添加 class el-row--flex,开启 flex 布局。

justify 用于设置 flex 布局下的水平排列方式,可选值start/end/center/space-around/space-between,生成的样式 is-justify-[justify],用于设置 justify-content 属性。 其他值生成的样式无效。

align 用于设置 flex 布局下的垂直排列方式,可选值top/middle/bottom,生成的样式 is-align-[align],用于设置 align-items 属性。 其他值生成的样式无效。

元素默认布局不会生成 flex 样式 justify !== 'start' ? 'is-justify-' + justify : '',align !== 'top' ? 'is-align-' + align : '',

系统基于 Flex 布局,允许子元素在父节点内的水平对齐方式 - 居左、居中、居右、等宽排列、分散排列。子元素与子元素之间,支持顶部对齐、垂直居中对齐、底部对齐的方式。

Flex 布局,可以简便、完整、响应式地实现各种页面布局。其语法本文不做过多赘述,详见 “Flex 布局教程”,阮一峰

计算属性

计算属性 style 通过为 row 组件设置负值 margin 从而抵消掉为 col 组件设置的 padding,也就间接为“行(row)”所包含的“列(column)”抵消掉了padding

0x03 Col 列组件

packages/col/src/col.js 使用渲染函数构建组件,支持渲染自定义元素标签。

render()

组件根据指定自定义元素渲染标签节点,由组件 prop 属性值动态计算添加 class 和 自定义样式,内部提供一个匿名插槽用于分发内容。

若自定义元素标签为<div>,等同于如下 template 实现。

组件 props

定义了 10 个 prop ,具体功能详见中文注释。 span 默认值 24,对应栅格系统 24 分栏。

计算属性

计算属性gutter 获取父组件 rowgutter值 。通过 row 组件的自定义 property 进行判断parent.$options.componentName !== 'ElRow'

组件 padding

若计算属性gutter值不为 0,计算 col 的左右 padding。

组件 class

分栏、间隔、左右偏移

栅格、间隔、左右偏移的样式动态计算。

col组件样式 scss 实现。 由.el-col-0可知,当 span 设置为 0 时,组件 display 值为none ,不会被渲染。

响应式布局

响应式布局样式动态计算。预设四个响应尺寸:xs sm md lg。 传入数字的话只会影响 span,还可以传入对象{span: 4, offset: 4} ,属性可选范围 span/offset/pull/push

使用指令 res 生成 @media 媒体查询样式,其 scss 实现如下:

0x04 Column Gutter 实现原理

通过 rowcol 组件,并通过 col 组件的 span 属性可以自由地组合布局。使用 <el-col :span="12" /> 来创建二个等宽的列。 使用 row 组件提供 gutter 属性来指定每一栏之间的间隔,默认单位为 px

以下代码创建一个包含二个等宽的列的行,间隔为 24px。

页面渲染后效果如下 👇:

image.png

列与列的间隔距离等于属性值 gutter,首列左侧 和 尾列的右侧间隔值为 gutter/2。布局如下 👇:

image.png

组件col中的计算属性 gutter获取父组件 rowgutter 值,并在 render() 中基于计算属性 gutter的值计算列的 padding-left padding-right,值为 gutter / 2 + 'px'

列与列的间隔距离等于属性值 gutter 等于 左列的 padding-right值 加上 右列的 padding-left值;首列左侧间隔值为 padding-left ; 尾列的右侧间隔值为 padding-right。效果如下 👇:

image.png

其它 3 等列、4 等列、……、24 等列依次类推,感觉是不是很好理解! 那组件row的计算属性 style 设置 margin-left margin-right负值用意何在

前文中提到,组件 row 的计算属性 style 通过为组件设置负值 margin 从而抵消掉为 col 组件设置的 padding,也就间接为“行(row)”所包含的“列(column)”抵消掉了padding

接下来通过示例、图解的方式对其进行阐释。

在之前的示例中第一行第一列中插入一行(该行中包含两等宽列),代码如下 👇:

假设组件 row 没有设置负值, margin值为 0 。 此时第一行第一列中嵌套的两列的间隔比默认的设置多出来一个 padding 值(gutter/2)。中间两列的间隔就 gutter/2 * 3。多嵌套一层,间隔就会增大 gutter/2。实现效果如下 👇:

image.png

若组件 row 的计算属性 style 通过为组件设置负值 margin,绝对值为 gutter/2。嵌套中的 row宽度会增加gutter,抵消掉为 col 组件设置的 padding,相当于此列没有设置 padding值。实现效果如下 👇:

image.png

基于此逻辑,不管进行多少层级的嵌套,都能保证列与列之间的间隔一致。代码实际渲染效果如下 👇:

image.png

0x05 样式实现

Row 组件

组件样式源码 packages\theme-chalk\src\row.scss 使用混合指令 bmutils-clearfix嵌套生成组件样式。

使用 gulpfile.js编译 scss 文件转换为CSS,经过浏览器兼容、格式压缩,最后生成 packages\theme-chalk\lib\row.css,内容格式如下。


Col 组件

组件样式源码 packages\theme-chalk\src\col.scss 生成组件样式实现分栏、间隔、偏移、响应式功能。

分栏、间隔、偏移

使用@for循环生成 024 对应样式:

  • span 栅格占据的列数,通过 width 来实现 ,对应样式 .el-col-[n]

  • offset 栅格左侧的间隔格数,通过 margin-left 实现 ,对应样式 .el-col-offset-[n]

  • push 栅格向右移动格数,通过 left 实现 ,对应样式 .el-col-push-[n]

  • pull 栅格向左移动格数,通过 right 实现,对应样式 .el-col-pull-[n]

组件栅格系统使用 24 分栏,所有每分栏宽度基准为 (1 / 24 * 100) * 1%

响应式布局

系统预设五个响应尺寸:xs sm md lg xl。使用指令 res 生成媒体查询,从而实现响应式设计。

0x06 📚 参考

“渲染函数 & JSX”,vuejs.org "媒体查询",MDN “@media”,MDN

最后更新于