amis HBox 水平布局组件详解:从 JSON 配置到 Flex 实现原理
2026/9/13 16:56:26 网站建设 项目流程

amis HBox 水平布局组件详解:从 JSON 配置到 Flex 实现原理

【免费下载链接】amis前端低代码框架,通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis

HBox 是 amis 低代码框架内置的水平布局渲染器,通过type: "hbox"一条 JSON 配置即可将多个子渲染器横向排列为等宽或自定义宽度的多列布局。本文以 docs/zh-CN/components/hbox.md 为骨架,结合 HBox 渲染器源码、布局样式 与 单元测试,完整讲解 HBox 的属性表、列集合写法、间距与对齐控制,以及底层 Flex 布局的实现细节。

基本用法

HBox 使用columns数组描述列集合,每个成员可以是普通字符串,也可以是任意 SchemaNode 渲染器节点。列成员上通过columnClassName指定该列容器额外的 CSS 类名,用于控制宽度、边框、背景等视觉样式。

一个典型的双列示例:

[ { "type": "hbox", "className": "b-a bg-dark lter", "columns": [ { "type": "plain", "text": "Col A", "columnClassName": "wrapper-xs b-r" }, "Col B" ] }, { "type": "hbox", "className": "b-a m-t bg-dark lter", "columns": [ { "type": "plain", "text": "w-md", "columnClassName": "w-md wrapper-xs bg-primary b-r" }, "..." ] } ]

要点说明:

  • 第一组 HBox 展示了两列平均分配的效果:columns中第一个成员是带columnClassNameplain文本渲染器,第二个成员是纯字符串"Col B"(会被 amis 自动包装渲染);
  • 第二组 HBox 通过columnClassName: "w-md wrapper-xs bg-primary b-r"把第一列固定为w-md宽度,其余列自动分配剩余空间,实现"固定列 + 自适应列"的经典布局;
  • className作用于 HBox 外层 DOM,示例中使用了 amis 内置的边框(b-a)、背景(bg-darkbg-primary)与外边距(m-t)工具类。

混合宽度与等宽分配

HBox 的默认行为是所有列等宽分配(详见下文 Flex 原理)。从 HBox 测试用例 可以看到五种列混排的写法:前三列分别通过columnClassName: 'w-xs''w-sm''w'固定宽度,后两列不指定宽度自动均分剩余空间。其快照(HBox.test.tsx.snap)表明渲染出的 DOM 结构为:

div.cxd-Hbox.cxd-Hbox--xs ├── div.cxd-Hbox-col.w-xs ├── div.cxd-Hbox-col.w-sm ├── div.cxd-Hbox-col.w ├── div.cxd-Hbox-col ← 未指定宽度,等宽 └── div.cxd-Hbox-col ← 未指定宽度,等宽

属性表

下表在原文档属性表基础上,补充了 AMISHBoxSchema 与 AMISHBoxColumn 类型定义中额外声明的属性:

属性名类型默认值说明
typestring"hbox"指定为 HBox 渲染器
classNamestring外层 Dom 的类名
gap'xs' \| 'sm' \| 'base' \| 'none' \| 'md' \| 'lg''xs'水平间距
valign'top' \| 'middle' \| 'bottom' \| 'between'垂直对齐方式
align'left' \| 'right' \| 'between' \| 'center'水平对齐方式
columnsArray列集合
columns[x]SchemaNode成员可以是其他渲染器
columns[x].columnClassNamestring"wrapper-xs"列上类名
columns[x].valign'top' \| 'middle' \| 'bottom' \| 'between'当前列内容的垂直对齐
columns[x].widthnumber \| string列宽度,'auto'时自适应内容
columns[x].heightnumber \| string列高度
columns[x].styleobject其他样式,直接写入列 DOM
columns[x].mode'normal' \| 'inline' \| 'horizontal'列内子表单项默认展示方式
columns[x].horizontalFormHorizontal水平排版下左右宽度占比细化
columns[x].visibleboolean该列是否显示
columns[x].visibleOnAMISExpression是否显示表达式(数据驱动)
subFormMode'normal' \| 'inline' \| 'horizontal'列内子表单项默认展示方式(作用于整个 HBox)
subFormHorizontalFormHorizontal列内水平排版的左右宽度占比(作用于整个 HBox)

说明一:gap默认值。原文档未标注默认值,但 HBox 的 defaultProps 明确声明gap: 'xs',因此未配置gap时列间默认采用xs档位的水平间距,'none'可彻底取消间距。

说明二:columns[x]链接。原文档中columns[x]指向 SchemaNode,即 amis 的通用节点类型文档,位于 docs/zh-CN/types/schemanode.md。

源码实现:HBox 的渲染流程

HBox 渲染器定义在 packages/amis/src/renderers/HBox.tsx,核心类HBox通过@Renderer({type: 'hbox'})装饰器注册为 amis 渲染器。其渲染流程可以概括为三层:

  1. 外层容器(render 方法):渲染一个根<div>,类名由Hbox基础类、classNamegapHbox--{gap})、valignHbox--v{Valign})、alignHbox--h{Align})组合而成,style原样透传;
  2. 列容器(renderColumn 方法):遍历columns,为每列生成一个Hbox-coldiv,根据column.width是否为'auto'、是否有自定义宽度,分别附加Hbox-col--autoHbox-col--customWidth类名,并把widthheightstyle合并写入行内样式;
  3. 列内容渲染(renderChild 方法):通过 amis 的render(region, node, props)递归渲染列内的子节点,并向子节点传递formModeformHorizontal(优先取列上的column.mode/column.horizontal,其次取subFormMode/subFormHorizontal,最后回落全局formMode/formHorizontal)。

值得注意的细节:renderColumn中先通过isVisible(column, data)判断列的visible/visibleOn,因此可以在 JSON 中按数据条件动态隐藏某一列;列内容被渲染为column/${key}区域,确保每列拥有独立的渲染作用域。

布局原理:基于 Flex 的等宽与间距实现

HBox 的样式定义在 packages/amis-ui/scss/layout/_hbox.scss,全部基于 CSS Flexbox 实现,不依赖栅格系统:

  • 外层.Hbox声明display: flex; flex-direction: row; flex-wrap: nowrap,即单行横向排列、不换行;
  • 默认列.Hbox-col声明flex-basis: 0; flex-grow: 1; width: 100%,这正是"所有列等宽分配"的实现基础——每列可伸缩基数相同,剩余空间被均分;
  • 指定宽度后列会附加Hbox-col--customWidth,样式置为flex-grow: unset; flex-basis: unset,列宽完全由行内width决定,其余列继续均分剩余空间;
  • 宽度为'auto'时列附加Hbox-col--auto,样式为flex: 0 0 auto; width: auto,列宽收缩为内容宽度,且不可伸缩。

gap的实现方式比较特别:外层容器使用负 margin(margin-left/right: calc(var(--gap-*)) * -0.5),列内部使用正 padding(padding-left/right: calc(var(--gap-*)) * 0.5),从而在不改变列宽计算的前提下形成均匀的列间距。xs / sm / base / md / lg各档位对应的间距尺寸由主题变量--gap-*定义(如--gap-xs: var(--sizes-size-3),见 packages/amis-ui/scss/_properties.scss),开发者可通过主题定制统一调整。

对齐方式:水平 align 与垂直 valign

HBox 同时支持水平与垂直两个维度的对齐,由源码中类名映射与样式共同完成:

维度属性取值生成的类名样式效果
水平alignleft无附加类默认左对齐(justify-content不设置)
水平alignrightHbox--hRightjustify-content: flex-end
水平aligncenterHbox--hCenterjustify-content: center
水平alignbetweenHbox--hBetweenjustify-content: space-between
垂直valigntop无附加类默认顶部对齐
垂直valignmiddleHbox--vMiddle列内flex-direction: column; justify-content: center
垂直valignbottomHbox--vBottom列内flex-direction: column; justify-content: flex-end
垂直valignbetweenHbox--vBetween列内flex-direction: column; justify-content: space-between

类名映射逻辑位于 HBox 的 render 方法:垂直对齐通过Hbox--v{ucFirst(valign)}拼装,水平对齐通过Hbox--h{ucFirst(align)}拼装。此外,单列还可以覆盖整体对齐columns[x].valign会在列容器上生成Hbox-col--v{Valign}类名(见 renderColumn),对应样式.Hbox > .Hbox-col--vTop/vMiddle/vBottom/vBetween只作用于当前列,方便实现"整体居中对齐、某列底部对齐"等混合效果。

列条件渲染与表单模式透传

除原文档属性表列出的字段外,源码还支持两类实用能力:

  1. 列级条件渲染columns[x].visiblecolumns[x].visibleOn(AMISHBoxColumn 定义)结合isVisible(column, data)判断,可依据页面数据动态显示/隐藏某一列,常用于按角色或业务状态切换列展示;
  2. 表单排版模式透传:当 HBox 列内嵌套表单项时,mode/horizontal(列级)与subFormMode/subFormHorizontal(HBox 级)会逐层透传给子渲染器(renderColumn 中的传参),使 HBox 可以直接作为表单的水平分段容器使用,无需在每个表单项上重复声明排版方式。

结语

HBox 是 amis 中实现"横向多列布局"的最小成本方案:默认等宽、可选固定/自适应宽度、支持两维对齐与数据驱动显隐,底层只依赖 Flex 的几条规则,性能与可定制性俱佳。其完整类型定义、默认值与渲染逻辑可在 HBox.tsx 中查阅,样式细节可在 _hbox.scss 中验证,测试用例与渲染快照分别在 HBox.test.tsx 与 HBox.test.tsx.snap。若需要更复杂的栅格响应式布局,可参考 amis 的 Grid 等布局组件,HBox 适用于简单、确定的多列场景。

【免费下载链接】amis前端低代码框架,通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询