- 前端
- UI组件
【免费下载链接】rsuite
🧱 A suite of React components .
导读
本文基于 rsuite 官方文档的 inline 布局示例 展开,深入讲解如何在 RSUITE 表单中使用layout="inline"让表单项在水平方向单行排列,并顺带掌握Form.Control、Form.Group、Form.Text、PasswordInput、HStack等核心子组件的组合用法。读完本文,你将能直接复刻一个可运行的"用户名 + 密码 + 登录按钮"单行登录表单,并理解其底层布局机制与无障碍(ARIA)关联原理。
一、inline 布局是什么:让表单一行排下
在 rsuite 的Form组件中,layout属性控制表单内部元素的排列方向,可取值如下(定义见 src/Form/Form.tsx):
| 取值 | 说明 |
|---|---|
vertical(默认) | 标签在上、控件在下,垂直堆叠 |
horizontal | 标签在左、控件在右,左右两列排布 |
inline | 表单项在水平方向内联排列,一行排下多个字段 |
inline布局特别适合搜索条件区、过滤器、登录框、短表单等场景:它让多个字段(如用户名、密码)和操作按钮(如登录)在同一行内紧凑排列,视觉上不占纵向空间。
值得注意的是,layout并非由Form组件自己实现,而是交给FormStack(即Form.Stack子组件)渲染。在 src/Form/Form.tsx 中可以看到:
const formChild = useMemo(() => { return fluid || layout ? ( <FormStack fluid={fluid} layout={layout}> {children} </FormStack> ) : ( children ); }, [fluid, children, layout]);也就是说,只要给Form传了layout,所有子元素都会被包进Form.Stack中统一编排。而 FormStack 内部是标准的 Flexbox 容器,其样式定义在 src/FormStack/styles/index.scss:
.rs-form-stack { --rs-form-stack-dir: column; --rs-form-stack-spacing: calc(var(--rs-spacing) * 4); display: flex; flex-direction: var(--rs-form-stack-dir); gap: var(--rs-form-stack-spacing); align-items: flex-start; } .rs-form-stack-inline { --rs-form-stack-dir: row; }inline模式本质上是把 Flex 主轴方向从column切换为row,表单项之间通过gap变量保持统一间距——布局的源码依据一目了然。对应的单元测试也在 src/Form/test/Form.spec.tsx 中验证了这一行为:
it('Should be inline', () => { render(<Form aria-label="form" layout="inline" />); expect(screen.getByRole('form')).to.have.contain('.rs-form-stack-inline'); });二、完整的 inline 登录表单示例(文档原例)
以下是文档 inline.md 提供的完整可运行示例,展示了一个典型的单行登录表单:
import EyeCloseIcon from '@rsuite/icons/EyeClose'; import VisibleIcon from '@rsuite/icons/Visible'; import { Form, Button, HStack, InputGroup, Input, PasswordInput } from 'rsuite'; const App = () => ( <> <Form layout="inline"> <Form.Group controlId="username-7"> <Form.Label>Username</Form.Label> <HStack> <Form.Control name="username" w={200} /> <Form.Text tooltip>Required</Form.Text> </HStack> </Form.Group> <Form.Group controlId="password-7"> <Form.Label>Password</Form.Label> <Form.Control name="password" type="password" autoComplete="off" accepter={PasswordInput} /> </Form.Group> <Button appearance="primary">Login</Button> </Form> </> ); ReactDOM.render(<App />, document.getElementById('root'));要点拆解:
<Form layout="inline">:声明 inline 布局,所有字段水平排布。<Form.Group>+controlId:每一个"标签 + 控件"组合用一个Form.Group包裹,controlId是这一组的唯一标识。<Form.Label>:渲染字段标签。它会自动从Form.Group上下文读取controlId,把htmlFor指向对应的表单控件(见 src/FormControlLabel/FormControlLabel.tsx)。<HStack>包裹控件与提示:HStack让"输入框 + 必填提示图标"横向对齐,控件宽度通过w={200}显式指定,避免 inline 布局下宽度不定。<Form.Text tooltip>:必填提示以 tooltip 形式呈现。tooltip为true时,FormHelpText会渲染一个问号图标,悬停/聚焦时通过 Whisper + Tooltip 弹出提示内容(见 src/FormHelpText/FormHelpText.tsx)。accepter={PasswordInput}:把默认输入控件替换为带"眼睛"切换图标、支持明文/密文切换的密码输入框。<Button appearance="primary">Login</Button>:inline 布局下按钮直接作为表单子元素参与横向排列,无需额外包装。
三、Form.Group:标签、控件与提示的关联纽带
inline 布局虽然"一行排下",但每个字段仍然是"标签 + 控件"的完整语义单元,这个单元就是Form.Group。它在 src/FormGroup/FormGroup.tsx 中的职责很清晰:
- 通过
useUniqueId为controlId生成稳定唯一 ID; - 把
controlId放入FormGroupContext,供子组件读取; - 渲染
role="group"的容器,把标签和控件"绑定"在一起。
Form.Group的controlId起着核心的无障碍串联作用(注释见 src/FormGroup/FormGroup.tsx):
- 它被设置到
Form.Control的id上; - 它被用作
Form.Label的htmlFor; - 它派生出
aria-labelledby(指向标签)和aria-describedby(指向帮助文本),让屏幕阅读器能够正确地把标签、提示和输入框关联起来。
在 src/FormControl/FormControl.tsx 中可以看到,Form.Control会从useFormGroup(id)读取controlId、helpTextId、labelId、errorMessageId,再把这些 ID 分别写入控件的aria-labelledby、aria-describedby、aria-invalid与aria-errormessage属性(见 src/FormControl/FormControl.tsx)。这意味着 inline 布局下的表单同样具备完整的无障碍语义,不会被屏幕阅读器误读为"平铺的裸输入框"。
四、Form.Control:数据收集与校验的入口
示例中每个字段都通过Form.Control承接表单数据,核心属性如下(类型定义见 src/FormControl/FormControl.tsx):
| 属性 | 作用 |
|---|---|
name | 字段名,用于读写表单值,必填 |
accepter | 渲染的实际输入组件,默认是Input,可替换为PasswordInput、Textarea、NumberInput等 |
type | 透传给底层输入控件的 HTML type,如password、email |
autoComplete | 透传原生自动完成属性,密码框建议设off |
w | 内联样式宽度(如w={200}),inline 布局下用于固定控件宽度 |
value/defaultValue | 受控与非受控取值 |
checkTrigger | 覆盖Form上的校验触发时机(change/blur/none) |
rule | 单字段校验规则(配合 schema-typed) |
errorMessage/errorPlacement | 手动指定错误信息及其展示位置 |
checkAsync | 异步校验开关 |
Form.Control内部会通过useFormControl把字段值、错误、onChange/onBlur与 FormContext 打通(见 src/FormControl/FormControl.tsx),并将校验结果渲染为FormErrorMessage(role="alert")。因此 inline 表单同样天然支持字段级校验与错误提示,只是错误信息默认出现在控件下方(errorPlacement="bottomStart"),在紧凑布局下要注意留出空间。
五、PasswordInput:密码字段的现代交互
示例用accepter={PasswordInput}替换默认输入框,得到带"显示/隐藏"切换的密码控件。它在 src/PasswordInput/PasswordInput.tsx 中提供的属性包括:
| 属性 | 说明 |
|---|---|
visible/defaultVisible | 控制/默认密码是否可见 |
startIcon/endIcon | 前置/后置自定义图标 |
renderVisibilityIcon | 自定义可见性切换图标 |
onVisibleChange | 可见性变化回调 |
其实现要点(见 src/PasswordInput/PasswordInput.tsx):
- 内部由
InputGroup inside包裹一个普通Input; - 输入框
type在visible ? 'text' : 'password'之间切换; - 内置
autoComplete="off",与示例中的显式设置一致; - 后置按钮通过
EyeCloseIcon/VisibleIcon切换图标,tabIndex={-1}避免干扰 Tab 焦点序列,并带有aria-label="Toggle password visibility"提升无障碍体验。
因此在 inline 布局中使用PasswordInput,既可以"一行排下"保持紧凑,又能提供完整的密码可见性交互,无需再手动拼装InputGroup+ 图标按钮。
六、HStack 与 Form.Text:紧凑布局下的辅助提示
inline 布局空间有限,必填提示如果直接以纯文本呈现会占宽度。示例采用了两级处理:
HStack将控件与提示图标水平对齐,并可通过w={200}固定控件宽度,保证提示图标位置稳定;Form.Text tooltip把提示折叠为问号图标(HelpOutlineIcon),悬停/聚焦时弹出 Tooltip,提示内容为Required。这一行为来自FormHelpText的tooltip分支:当tooltip为true时,组件渲染Whisper + Tooltip结构,并保留id=helpTextId供aria-describedby引用(见 src/FormHelpText/FormHelpText.tsx)。
由此,inline 表单既能保持信息完整(必填说明仍然可读),又不牺牲横向空间。
七、inline 布局的适用场景与注意事项
推荐场景:
- 登录、注册等字段较少的单行表单;
- 列表页顶部的组合筛选条件区;
- 需要与其他 UI 元素(如工具栏按钮)横向对齐的短表单。
注意事项:
- 控件宽度:inline 布局下输入控件默认宽度可能随内容伸缩,建议像示例一样用
w={200}等显式宽度,或在外层用HStack/Stack固定尺寸。 - 错误提示空间:字段校验错误默认渲染在控件下方(
bottomStart),紧凑布局下可能挤压相邻元素,必要时通过errorPlacement调整,或在Form.Group中预留空间。 - 与
fluid的关系:Form的fluid属性让输入控件占满容器宽度,官方注释明确其"仅在垂直布局(vertical)下生效"(见 src/Form/Form.tsx),因此 inline 布局下不要依赖fluid,应使用宽度属性控制尺寸。 - 响应式:inline 布局在一行排布多个字段,当容器变窄(如移动端)时容易溢出,建议结合响应式宽度或在小屏改用 vertical 布局。
- 与其他布局的对比:需要"标签在左、控件在右"的纵向分组表单时,应改用
layout="horizontal"(示例见 horizontal.md);需要输入框铺满整行时,用默认vertical布局(示例见 basic.md 与 fluid.md)。
八、源码路径速查
| 关注点 | 仓库位置 |
|---|---|
| inline 布局示例(本文主体) | docs/pages/components/form/fragments/inline.md |
Form组件与layout属性 | src/Form/Form.tsx |
布局容器Form.Stack | src/FormStack/FormStack.tsx |
| 布局样式(Flex 主轴切换) | src/FormStack/styles/index.scss |
布局单元Form.Group | src/FormGroup/FormGroup.tsx |
字段控制Form.Control | src/FormControl/FormControl.tsx |
标签Form.Label | src/FormControlLabel/FormControlLabel.tsx |
帮助/提示文本Form.Text | src/FormHelpText/FormHelpText.tsx |
密码输入PasswordInput | src/PasswordInput/PasswordInput.tsx |
| inline 布局的测试验证 | src/Form/test/Form.spec.tsx |
小结
RSUITE 的Form layout="inline"提供了一条极简路径,让多字段表单以单行水平排列,特别适合登录框、筛选区等紧凑场景。通过本文的完整示例,你可以直接组合Form.Group、Form.Label、Form.Control、HStack、Form.Text tooltip与PasswordInput,在保持字段语义和无障碍关联完整的同时,获得一行排下的清爽布局。若需深入自定义,可直接阅读上文列出的源码文件,理解Form.Stack的 Flexbox 实现、Form.Group的 ID 串联机制与Form.Control的数据流,即可举一反三地调整间距、宽度与校验行为。
- 前端
- UI组件
【免费下载链接】rsuite
🧱 A suite of React components .
相关推荐
ng-zorro-antd 内联登录栏(Inline Login Form)完整实战指南:基于 nzLayout="inline" 的表单布局与校验实现
ng zorro antd 内联登录栏(Inline Login Form)完整实战指南:基于 nzLayout="inline" 的表单布局与校验实现 导读
UI组件前端ant-design 行内表单(Inline Form)实战:从登录界面 Demo 到源码级解析
ant design 行内表单(Inline Form)实战:从登录界面 Demo 到源码级解析 行内表单(Inline Form)是 ant design 提
UI组件前端设计系统RSUITE 表单实战指南:基于 Form 垂直布局搭建基础表单的完整拆解
RSUITE 表单实战指南:基于 Form 垂直布局搭建基础表单的完整拆解 RSUITE 的 Form 组件是一套完整的表单数据收集与校验方案。本文以官方文档中
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考