ant-design Checkbox 多选框组件完全指南:从基础用法、分组全选到表单集成与语义化定制
Checkbox 是 ant-design(组件总目录)中负责"多项选择收集"的数据录入组件。本文以该组件的官方中文文档为骨架,结合仓库内的真实源码(Checkbox.tsx、Group.tsx)与示例代码,带你全面掌握独立多选框、Checkbox.Group 分组、全选/半选(indeterminate)、在 Form.Item 中的绑定方式,以及 6.0.0 新增的 Semantic DOM 语义化定制能力。读完你将能够在真实业务中正确选择受控/非受控模式、构造可复用的分组选择逻辑,并在需要时直接修改组件内部任意结构单元的样式。
何时使用
根据官方文档,Checkbox 适用于两类场景:
- 在一组可选项中进行多项选择时;
- 单独使用时表示两种状态之间的切换,此时它和
switch类似,但两者语义不同:切换switch会直接触发状态改变;而checkbox一般用于状态标记,通常需要与提交操作配合(例如"我已阅读并同意协议"这类勾选确认)。
一句话区分:多选场景优先考虑 Checkbox.Group,二选一且需要立即生效的动作使用 switch,二选一但仅作为待提交状态标记则使用单个 Checkbox。
从演示出发:六类典型场景
组件目录(components/checkbox/demo)中提供了丰富的可运行示例,其中正式演示(非 debug)包含:
- basic.tsx:基本用法,单个 Checkbox +
onChange回调; - disabled.tsx:不可用状态;
- controller.tsx:受控的 Checkbox;
- group.tsx:Checkbox 组;
- check-all.tsx:全选与半选联动;
- layout.tsx:布局排列;
- style-class.tsx(自 6.0.0):自定义语义结构的样式和类。
此外还有若干 debug 示例(同行布局、禁用下 Tooltip、Group 内等宽、自定义 lineWidth 等),用于回归验证边界样式,一般场景无需关注。
基本用法与受控切换
单个 Checkbox 的 onChange 事件会返回 CheckboxChangeEvent,可通过 e.target.checked 读取最新选中态:
import React from 'react';
import { Checkbox } from 'antd';
import type { CheckboxProps } from 'antd';
const onChange: CheckboxProps['onChange'] = (e) => {
console.log(`checked = ${e.target.checked}`);
};
const App: React.FC = () => <Checkbox onChange={onChange}>Checkbox</Checkbox>;
export default App;
从源码看,Checkbox.tsx 内部通过 useControlledState(defaultChecked, checked) 同时支持受控与非受控两种模式:传入 checked 即为受控组件,状态由外部接管;只传 defaultChecked 则由内部 state 自行维护。这在 controller 演示中体现得最直观——用户完全可以通过按钮去改变传入的 checked 值,实现外部触发选中切换。
Checkbox.Group:分组多项选择
当有多个并列选项时,推荐直接使用 Checkbox.Group,其 options 支持三种形态:纯字符串数组、纯数字数组,以及 Option 对象数组。以官方 group.tsx 为例:
import React from 'react';
import { Checkbox } from 'antd';
import type { CheckboxOptionType } from 'antd';
const plainOptions = ['Apple', 'Pear', 'Orange'];
const options: CheckboxOptionType<string>[] = [
{ label: 'Apple', value: 'Apple', className: 'label-1' },
{ label: 'Pear', value: 'Pear', className: 'label-2' },
{ label: 'Orange', value: 'Orange', className: 'label-3' },
];
const App: React.FC = () => (
<>
<Checkbox.Group options={plainOptions} defaultValue={['Apple']} />
<Checkbox.Group options={options} defaultValue={['Pear']} />
</>
);
export default App;
Group 的 onChange 回调不再返回事件对象,而是直接给出当前全部选中值的数组(checkedValue: T[])。结合 Group.tsx 可以看到其内部协作机制:
- 子 Checkbox 勾选时通过
GroupContext触发toggleOption,在value数组中增删对应选项; - 回调前会对结果做两件事:过滤掉尚未注册的值(
registeredValues),并按options声明顺序排序,保证输出稳定有序; - 每个子项通过
registerValue/cancelValue向 Group 注册与注销自己的 value(详见 GroupContext.ts)。
值得注意的是,即便不传 options,也可以把若干个 Checkbox 直接放在 Checkbox.Group 内作为 children,此时它们会通过 Context 共享同一套选中集合。Group 会把自身的 disabled、name 通过 Context 传递给内部每一个 Checkbox(见 Checkbox.tsx 对 checkboxGroup.disabled 的合并逻辑)。
全选与半选(indeterminate)
indeterminate 是本组件最具代表性的能力之一:它表示"部分选中",视觉上渲染为短横线,只负责样式控制,不改变真实选中状态,实际选中值仍由外层逻辑决定。官方 check-all.tsx 展示了经典的全选联动模式:
import React, { useState } from 'react';
import { Checkbox, Divider } from 'antd';
import type { CheckboxProps } from 'antd';
const CheckboxGroup = Checkbox.Group;
const plainOptions = ['Apple', 'Pear', 'Orange'];
const defaultCheckedList = ['Apple', 'Orange'];
const App: React.FC = () => {
const [checkedList, setCheckedList] = useState<string[]>(defaultCheckedList);
const checkAll = plainOptions.length === checkedList.length;
const indeterminate = checkedList.length > 0 && checkedList.length < plainOptions.length;
const onChange = (list: string[]) => setCheckedList(list);
const onCheckAllChange: CheckboxProps['onChange'] = (e) => {
setCheckedList(e.target.checked ? plainOptions : []);
};
return (
<>
<Checkbox indeterminate={indeterminate} onChange={onCheckAllChange} checked={checkAll}>
Check all
</Checkbox>
<Divider />
<CheckboxGroup options={plainOptions} value={checkedList} onChange={onChange} />
</>
);
};
export default App;
这里两个状态判定值得记住:indeterminate = 已选中 0 < 数量 < 总数,checkAll = 已选中数量 === 总数;"全选"按钮点击后按 e.target.checked 一次性写入全部或清空。源码层面,indeterminate 通过 useEffect 直接设置原生 input 的 indeterminate 属性 实现,勾选对勾(:after 旋转 45°)与短横线的切换样式则由 style/index.ts 中的 &-indeterminate 规则渲染。
API 详解
通用属性(如 className、style、无障碍属性等)请参考 通用属性文档。以下为 Checkbox 系列专属 API。
Checkbox
| 参数 | 说明 | 类型 | 默认值 | 版本 | 全局配置 |
|---|---|---|---|---|---|
| checked | 指定当前是否选中 | boolean | false | × | |
| classNames | 用于自定义组件内部各语义化结构的 class,支持对象或函数 | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | 6.0.0 | |
| defaultChecked | 初始是否选中 | boolean | false | × | |
| disabled | 失效状态 | boolean | false | × | |
| indeterminate | 设置 indeterminate 状态,只负责样式控制 | boolean | false | × | |
| onChange | 变化时的回调函数 | (e: CheckboxChangeEvent) => void | - | × | |
| onBlur | 失去焦点时的回调 | function() | - | × | |
| onFocus | 获得焦点时的回调 | function() | - | × | |
| styles | 用于自定义组件内部各语义化结构的行内 style,支持对象或函数 | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | 6.0.0 |
关于上表中的全局配置列(× 表示不支持通过 ConfigProvider 的 componentConfig 全局覆盖),实现上与 Checkbox.tsx 中 useComponentConfig('checkbox') 读取的上下文有关:目前组件会从全局上下文合并 className/style/classNames/styles,但 checked、disabled 等行为型属性仍以组件自身 props 为准。
CheckboxChangeEvent 的结构在源码中有明确类型定义(Checkbox.tsx):
interface CheckboxChangeEvent {
target: CheckboxChangeEventTarget; // 含 checked: boolean
stopPropagation: () => void;
preventDefault: () => void;
nativeEvent: MouseEvent;
}
disabled 的合并优先级值得注意:源码中 mergedDisabled = disabled ?? checkboxGroup?.disabled ?? contextDisabled(Checkbox.tsx),即"自身 disabled > 所属 Group 的 disabled > ConfigProvider 的 DisabledContext"。这也是为何 Group 整组禁用时内部单项仍可单独恢复可用的原因。
Checkbox.Group
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| defaultValue | 默认选中的选项 | (string | number)[] | [] | |
| disabled | 整组失效 | boolean | false | |
| name | CheckboxGroup 下所有 input[type="checkbox"] 的 name 属性 |
string | - | |
| options | 指定可选项 | string[] | number[] | Option[] | [] | |
| value | 指定选中的选项 | (string | number | boolean)[] | [] | |
| title | 选项的 title | string |
- | |
| className | 选项的类名 | string |
- | 5.25.0 |
| style | 选项的样式 | React.CSSProperties |
- | |
| onChange | 变化时的回调函数 | (checkedValue: T[]) => void | - |
Option
interface Option {
label: string;
value: string;
disabled?: boolean;
}
需要说明的是,文档中的 Option 接口为最小示意。结合源码 Group.tsx,实际可用的 CheckboxOptionType 还包括 style、className(5.25.0+)、title、id、onChange、required 等字段,且 value 的约束更宽(内部支持 string | number | boolean)。options 为纯字符串/数字时,Group 会自动执行 { label: value, value } 的规范化映射(Group.tsx)。
方法
Checkbox
| 名称 | 描述 | 版本 |
|---|---|---|
| blur() | 移除焦点 | |
| focus() | 获取焦点 | |
| nativeElement | 返回 Checkbox 的 DOM 节点 | 5.17.3 |
使用示例:const ref = useRef<CheckboxRef>(null); ref.current?.focus();。组件本身由 React.forwardRef 导出,ref 类型为 CheckboxRef(来自 @rc-component/checkbox),见 Checkbox.tsx。
源码视角:几个值得了解的底层实现细节
1. label 双击冒泡锁(useBubbleLock)
原生 HTML 中,点击 <label> 会二次触发内部 input 的点击。为避免 onClick 被重复执行,组件通过 useBubbleLock.ts 在 label click 与 input click 之间建立一次 rAF 级别的锁:点击 label 时记录锁,随后 input 冒泡上来的点击若发现锁存在则直接 stopPropagation。这是将原生交互打磨成稳定 React 事件的典型处理。
2. Wave 水波效果
渲染结构最外层包裹了 <Wave component="Checkbox">(Checkbox.tsx),当用户点击时会产生 antd 标志性的点击水波纹反馈;disabled 状态下水波会被禁用。
3. RTL 与"选中框本体始终 LTR"
在 style/index.ts 中,选框本体被显式声明为 direction: 'ltr',这是为了避免 RTL 环境下对勾图形被镜像翻转;外层 wrapper 则会根据 ConfigProvider 的 direction 切换 -rtl 修饰类(Checkbox.tsx)。这类细节保证了在多语言/多方向站点中渲染一致。
4. 3D/样式依赖
样式由 style/index.ts 中的 genCheckboxStyle 生成:选框底色、对勾(:after 旋转 45° 白色粗线)、半选短横线、hover 态(边框/填充变 colorPrimaryHover)、focus-visible 外轮廓等都基于 Design Token 计算(如 colorBgContainer、colorBorder、colorPrimary、colorPrimaryHover、checkboxSize 等),并支持 motion 动效关闭(genNoMotionStyle)。
在 Form.Item 中绑定数据(FAQ)
官方 FAQ 特别指出一个高频踩坑点:为什么在 Form.Item 下不能绑定数据?
原因在于 Form.Item 默认把表单值绑定到子组件的 value 属性上,而 Checkbox 的"值属性"是 checked。解决方法是通过 valuePropName 显式指定绑定的属性名:
<Form.Item name="fieldA" valuePropName="checked">
<Checkbox />
</Form.Item>
同样地,Checkbox.Group 在 Form 中遵循默认规则(Group 的值本身就是数组,通过 value/onChange 绑定),因此无需 valuePropName,可直接 name="xxx" 使用。组件内部会通过 FormItemInputContext 感知自己是否处于 Form.Item 中,从而给 wrapper 附加 -in-form-item 修饰类(Checkbox.tsx),保证在表单内的间距与对齐表现正确。
Semantic DOM:6.0.0 的语义化结构定制
自 6.0.0 起,Checkbox 支持对组件内部"语义化结构"做细粒度定制。根据 SemanticPreview 演示,整个组件被划分为三个语义节点:
| 语义节点 | 含义 |
|---|---|
| root | 根元素,包含行内 flex 布局、基线对齐、光标样式、重置样式等复选框容器的基础样式 |
| icon | 选中框元素,包含尺寸、方向、背景色、边框、圆角、过渡动画,以及选中状态的勾选标记样式 |
| label | 文本元素,包含文本的内边距和与复选框的间距样式 |
对应到 classNames/styles 属性(类型与结构见 Checkbox.tsx)。定制写法参考官方 style-class.tsx:
// 对象形式:直接指定各结构的行内 style
const styles: CheckboxProps['styles'] = {
icon: { borderRadius: 6 },
label: { color: 'blue' },
};
// 函数形式:根据 props 动态返回 classNames,例如按 checked 状态切换配色
const classNamesFn: CheckboxProps['classNames'] = (info) => {
if (info.props.checked) {
return {
root: clsx(styles.root),
icon: clsx(styles.icon, styles.iconChecked),
label: clsx(styles.label, styles.labelChecked),
};
}
return { root: styles.root, icon: styles.icon, label: styles.label };
};
函数形式的入参 { props } 提供了合并后的最新 props(含 checked、disabled、indeterminate),因此可以轻松实现"选中态换肤"等动态样式;对象/函数形式同样适用于 classNames 与 styles,且两者会与 ConfigProvider 上下文中注入的全局 classNames/styles 做合并。此外,复选框还保留了 -wrapper-checked、-wrapper-disabled 等状态修饰类,以及供自定义样式使用的语义化类前缀。
主题变量(Design Token)
Checkbox 的样式完全由 CSS-in-JS 的 token 驱动,主要受以下全局 Design Token 影响(均为 antd 主题体系标准 token,来源见 style/index.ts):
colorPrimary/colorPrimaryHover:选中态底色、边框与 hover 反馈色;colorBgContainer、colorBorder、colorWhite:选框底色、未选中边框色与对勾颜色;borderRadiusSM:选框圆角;checkboxSize、lineWidth、lineWidthBold:选框尺寸与线条粗细;paddingXS:选框与文本间距;marginXS:Group 内选项的列间距;motionDurationSlow/motionDurationMid/motionDurationFast与motionEaseOutBack/motionEaseInBack:勾选动画时长与缓动。
如需整体换肤,推荐通过 ConfigProvider 的 theme 修改这些 token;若仅需局部覆盖,则优先使用上面的 Semantic DOM classNames/styles,而不是手写 CSS 覆盖。
小结
- 场景选型:多项选择用
Checkbox.Group;单值状态标记用独立Checkbox(区别于直接生效的switch)。 - 状态模式:
defaultChecked/defaultValue走非受控,checked/value走受控;indeterminate仅表达"半选"外观,真实数据仍需自己维护。 - 数据与交互:Group 通过 Context 统一管理选中集合并保证回调有序;label 点击使用 rAF 锁避免事件重复触发。
- 表单集成:单个 Checkbox 务必配置
valuePropName="checked"。 - 精细化样式:6.0.0+ 使用
classNames/styles+ Semantic DOM(root/icon/label),或直接下沉到 Design Token 层做全局主题定制。
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 StartedRust0624
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