ant-design Form 中 warningOnly 规则详解:让校验警告不阻塞表单提交
本篇基于 warning-only 示例 与 Form 官方文档 的 Rule 配置说明,讲解 ant-design Form 组件中 warningOnly 规则属性的用途与用法:如何为字段配置“仅警告”级别的校验,使其展示警告提示却不触发 onFinishFailed、不阻止提交;并结合 Form.Item 源码 与测试用例,说明警告与错误在校验流程、必填星号、反馈图标和 useStatus 中的完整差异,适合需要在“强制校验 + 软性提示”之间做区分的表单场景。
一、warningOnly 解决的问题
默认情况下,Form.Item 的 rules 校验一旦失败,字段状态变为 error,form.submit() 会 reject 并触发 onFinishFailed,表单无法提交。但实际业务中并非所有校验都是“硬约束”,例如:
- URL 格式不规范但仍允许提交(后台会兜底纠正);
- 昵称长度偏短,只提示不阻断;
- 密码强度不够,给出警告但放行。
这类需求在 ant-design 中的做法就是在某条规则上添加 warningOnly: true。官方文档 Rule 表格 对其定义如下:
| 名称 | 说明 | 类型 | 版本 |
|---|---|---|---|
| warningOnly | 仅警告,不阻塞表单提交 | boolean | 4.17.0 |
也就是说,warningOnly 是 Rule 配置项的一个属性(自 4.17.0 起支持),作用是把该条规则校验失败产生的结果从 errors 降级为 warnings:UI 上依然展示提示文案,但提交流程不受影响。
二、完整示例:URL 字段只警告不阻断
仓库中的 warning-only 示例 展示了典型用法:一个 URL 字段同时挂了三条规则,中间一条格式校验标记为 warningOnly:
import React from 'react';
import { Button, Form, Input, message, Space } from 'antd';
const App: React.FC = () => {
const [messageApi, contextHolder] = message.useMessage();
const [form] = Form.useForm();
const onFinish = () => {
messageApi.success('Submit success!');
};
const onFinishFailed = () => {
messageApi.error('Submit failed!');
};
const onFill = () => {
form.setFieldsValue({
url: 'https://taobao.com/',
});
};
return (
<>
{contextHolder}
<Form
form={form}
layout="vertical"
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item
name="url"
label="URL"
rules={[
{ required: true }, // 必填:失败则阻塞提交
{ type: 'url', warningOnly: true }, // URL 格式:仅警告,不阻塞
{ type: 'string', min: 6 }, // 长度:失败则阻塞提交
]}
>
<Input placeholder="input placeholder" />
</Form.Item>
<Form.Item>
<Space>
<Button type="primary" htmlType="submit">Submit</Button>
<Button htmlType="button" onClick={onFill}>Fill</Button>
</Space>
</Form.Item>
</Form>
</>
);
};
export default App;
示例说明(对应 示例说明文档 中的描述):rule 添加 warningOnly 后校验不再阻塞表单提交。具体行为是:
- 输入框留空时,
required: true校验失败 → 字段报错,onFinishFailed被调用; - 输入了非 URL 字符串(长度 ≥ 6)时,
type: 'url'校验失败,但由于带warningOnly,字段仅显示警告态,点击 Submit 后onFinish依然被调用,弹出 “Submit success!”; - 点击 Fill 按钮通过
form.setFieldsValue填入合法 URL 后,警告消失。
warningOnly 既可以叠加在内置校验(如 type: 'url'、min、pattern)上,也可以叠加在 required 上;文档同时说明 Rule 支持 object 或 function 两种形式(type Rule = RuleConfig | ((form: FormInstance) => RuleConfig)),函数形式返回的 RuleConfig 中同样可以带 warningOnly。
三、源码视角:warningOnly 到底改变了什么
1. 校验结果进入 warnings 而非 errors
Form.Item 内部为每个字段维护 meta(见 genEmptyMeta),其中明确区分了两个数组:
function genEmptyMeta(): Meta {
return {
errors: [],
warnings: [],
touched: false,
validating: false,
name: [],
validated: false,
};
}
带 warningOnly 的规则校验失败后,错误文案被 rc-field-form 底层归类到 meta.warnings。Form.Item 源码 随后将自身的 meta.errors/meta.warnings 与所有 noStyle 子字段的结果合并为 mergedErrors 与 mergedWarnings,分别传给 ItemHolder 渲染帮助文案、aria-describedby 等。因此警告文案依然会展示在字段下方,只是不携带 has-error 的错误态。
2. warningOnly 的 required 不计入必填星号
在 Form.Item 渲染逻辑 中,isRequired 的推导会显式排除带 warningOnly 的规则:
const isRequired =
required !== undefined
? required
: rules?.some((rule) => {
if (
isPlainObject(rule) &&
(rule as RuleObject).required &&
!(rule as RuleObject).warningOnly
) {
return true;
}
if (isFunction(rule)) {
const ruleEntity = rule(context);
return ruleEntity?.required && !ruleEntity?.warningOnly;
}
return false;
});
这带来两个直接效果:
- 只有
{ required: true, warningOnly: true }的字段,label 前不会出现必填星号(因为星号由isRequired驱动); isRequired还会用于设置aria-required(源码 L392-L394),因此无障碍属性与星号表现保持一致。
3. 警告态样式类
字段出现 warnings 时,Form.Item 根节点会带上 ant-form-item-has-warning 类名,区别于错误态的 ant-form-item-has-error。测试用例 对此有直接断言:
it('warningOnly validate', async () => {
const { container } = render(
<Form>
<Form.Item>
<Form.Item
name="test"
label="test"
initialValue="bamboo"
rules={[{ required: true, warningOnly: true }]}
>
<Input />
</Form.Item>
</Form.Item>
</Form>,
);
await changeValue(0, 'test');
await changeValue(0, '');
expect(container.querySelector('.ant-form-item-with-help')).toBeTruthy();
expect(container.querySelector('.ant-form-item-has-warning')).toBeTruthy();
});
即清空 initialValue 后,字段展示了帮助信息且处于 warning 状态,而提交本身不会被这条 required 规则拦截。
四、与反馈机制的配合
1. hasFeedback 下的警告图标
Form.Item 的 hasFeedback 会根据校验状态自动派生 success / validating / warning / error 四类图标状态。测试 覆盖了这一组合:
<Form.Item name="warning" hasFeedback rules={[{ required: true, warningOnly: true }]}>
<Input />
</Form.Item>
...
expect(container.querySelector('.ant-form-item-has-warning')).toBeTruthy();
expect(container.querySelector('.ant-form-item-has-error')).toBeTruthy();
可以看到 warning 字段与 error 字段同时存在时,两者分别落在 has-warning / has-error 状态上,互不影响。
2. 用 useStatus 读取警告文案
自定义子组件可以通过 Form.Item.useStatus() 拿到当前字段的 errors 与 warnings,测试 演示了 warningOnly 消息进入 warnings 通道:
const WarningItem: React.FC = () => {
const { warnings } = useStatus();
return <div className="test-warning">{warnings[0]}</div>;
};
<Form.Item
name="warning"
rules={[{ required: true, message: 'This is a warning message.', warningOnly: true }]}
>
<WarningItem />
</Form.Item>
点击提交后,warnings[0] 即渲染出该条警告文案。文档中的 FieldData 表格 也把 warnings(string[] 类型的警告信息)与 errors 并列为字段元信息的一部分,配合 form.getFieldError、form.getFieldsFormat 等 API 可以编程化地读取警告结果。
五、使用建议与边界
结合示例与源码可以总结几条实践要点:
- 粒度是“规则级”而非“字段级”:
warningOnly写在某一条 rule 上,同一字段的其他规则失败仍会阻塞提交。示例中min: 6不带warningOnly,短于 6 个字符的输入照样会触发onFinishFailed。 - warningOnly + required 不产生星号:从 isRequired 推导逻辑 看,只有非 warningOnly 的 required 规则才标记必填;若需要“提示必填但实际放行”,应只保留 warningOnly 规则,不额外传
requiredprop。 - 版本前提:
warningOnly自 4.17.0 起支持,使用旧版本 antd 时需先确认版本(可在项目package.json中核对antd依赖)。 - 警告不是“静默”:warning 文案会出现在字段 help 区域并触发
ant-form-item-with-help/ant-form-item-has-warning样式,配合hasFeedback还有独立图标;它只是不阻断提交,并非不展示。
如果你需要在提交成功后再根据 warnings 做二次确认(例如弹框提示用户 URL 格式可疑),可以在 onFinish 中通过 form 实例读取各字段状态后再决定是否继续请求——warningOnly 让“提示”与“拦截”这两种校验意图在同一个 rules 数组里清晰分离,这正是 warning-only 示例 要演示的核心价值。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00