企业工作台模块化布局方案
需求
- 可自由拖动模块的位置、设置模块的宽度
- 可添加/移除模块
- 每一行的模块高度相等
- 部分模块有最大和最小宽度限制
- 当前用户无配置时使用默认模块布局
选型
使用 react-grid-layout 管理模块布局。
实现方案
栅格化布局
将内容区域宽度划分为 12 格,高度以 100px 为一格,模块的宽高以格为单位,假设内容区宽度为 1080px,那么 4x4 尺寸的模块在 react-grid-layout 中的效果就是 360px x 400px。
行内元素等高
由于 react-grid-layout 中的布局是基于绝对定位(position: absolute
)和变换(trasnform: translate(x, y)
)实现的,无法使用 block 和 flex 布局特性,若基于它实现行内模块等高的效果的话会比较复杂。
为了简化 react-grid-layout 相关代码的复杂度,目前可行的解决方法是将页面内容布局模式分为普通和编辑:
- 只读模式: 读取模块化配置,根据各个模块的几何属性(x、y、w、h)进行排版然后渲染到页面中,利用 flex 布局实现行内模块等高特性
- 编辑模式: 转换模块化配置然后交给 react-grid-layout 处理
这两种模式的布局代码可以划分到 DashboardFlowLayout 和 DashboardGridLayout 组件中,在切换到编辑模式时,获取 DashboardFlowLayout 组件中所有模块的实际高度并传给 DashboardGridLayout 组件,每当模块布局变化时,DashboardGridLayout 组件根据模块的实际高度重新排版,然后将行内模块最大高度作为行高并应用到所有模块。
排版的效果与浏览器渲染机制中的 reflow (回流) 相似,为了方便理解和引用相关资料,在实际代码中实现排版这一操作的函数已命名为 reflow,具体代码如下:
1 | function reflow(elements, maxWidth) { |
只读模式下的布局还原
编辑模式下的布局是基于 react-grid-layout 实现的,能够用 xy 灵活的控制模块位置,那么在基于 flex 布局的只读模式下如何还原模块的位置?
较为稳妥的做法是用空 div 元素填充模块之间的空白,空白 div 的宽度等于当前模块的 x 与上个模块的 x + width 的差值,即:width = el.x - (prevEl.x + prevEl.width)
。