Ant Design Checkbox 复选框组件完全指南:API 解析、Group 协同与源码级实践
导读
Checkbox 是 ant-design 组件库中用于"从多个选项中选择多个值"的基础交互组件,位于 Data Entry 分组之下,源码入口为 components/checkbox,对外通过 import { Checkbox } from 'antd' 使用。本文以 components/checkbox/index.en-US.md 官方 API 文档为骨架,深入组件源码与官方示例,系统讲解单选 Checkbox 与 Checkbox.Group 的完整用法:从基础勾选、禁用态、半选(indeterminate)、全选联动、Grid 布局搭配,到受控/非受控机制、语义化 DOM 定制与表单集成等实战要点,帮助读者彻底掌握这一高频表单组件的每一项配置与底层实现原理。
When To Use:何时使用 Checkbox
根据官方文档的定义,Checkbox 适用于以下两类场景:
- 从多个候选项中选中多个值:多选场景(即"多选题"),这是它与 Radio(单选)最本质的区别。多个 Checkbox 通常以
Checkbox.Group形式组织,由组统一维护选中值列表。 - 单复选框等同于两态开关:当只有一个 Checkbox 时,它与 Switch 在功能上都表示"开/关"两种状态。两者的关键区别在于交互反馈时机:Switch 会立即触发状态变更(点一下即切换),而 Checkbox 仅标记状态发生变化,通常需要配合"提交"按钮(如表单提交)才真正生效。因此在需要即时反馈的设置类 UI 中优先选择 Switch,而在表单提交类场景中使用 Checkbox。
基础示例与官方 Demo 全览
官方文档在 "Examples" 一节列出了 Checkbox 的全部演示案例,源文件均位于 components/checkbox/demo 目录,是上手最直接的参考资料:
| 示例 | Demo 源文件 | 说明 |
|---|---|---|
| Basic | basic.tsx | 最基础的单个 Checkbox 与 onChange 用法 |
| Disabled | disabled.tsx | 禁用态 |
| Controlled Checkbox | controller.tsx | 受控组件与禁用切换 |
| Checkbox Group | group.tsx | 选项组:字符串/对象两种 options |
| Check all | check-all.tsx | 全选/半选联动经典模式 |
| Use with Grid | layout.tsx | 与栅格布局结合 |
| Custom semantic dom styling | style-class.tsx | 语义化 DOM 定制(6.0.0+) |
Basic:单个 Checkbox 的最简形态
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;
注意 onChange 回调签名:(e: CheckboxChangeEvent) => void,选中状态通过 e.target.checked 读取。CheckboxProps['onChange'] 是官方推荐的类型标注方式,可避免手写回调类型。
Controlled Checkbox:受控勾选与禁用切换
单个 Checkbox 同样支持受控模式。参考 controller.tsx:
import React, { useState } from 'react';
import { Button, Checkbox } from 'antd';
import type { CheckboxProps } from 'antd';
const App: React.FC = () => {
const [checked, setChecked] = useState(true);
const [disabled, setDisabled] = useState(false);
const onChange: CheckboxProps['onChange'] = (e) => {
setChecked(e.target.checked);
};
return (
<>
<p>
<Checkbox checked={checked} disabled={disabled} onChange={onChange}>
{`${checked ? 'Checked' : 'Unchecked'}-${disabled ? 'Disabled' : 'Enabled'}`}
</Checkbox>
</p>
<Button onClick={() => setChecked(!checked)}>
{!checked ? 'Check' : 'Uncheck'}
</Button>
<Button onClick={() => setDisabled(!disabled)}>
{!disabled ? 'Disable' : 'Enable'}
</Button>
</>
);
};
从 Checkbox.tsx 的源码可以看到,组件通过 useControlledState(defaultChecked, checked) 同时支持受控与非受控两种模式:传入 checked 且配合 onChange 即为受控;只传 defaultChecked 则为非受控。内部回调 onInternalChange 会先更新内部状态,再向上触发 onChange,并在处于 Group 中时继续调用 checkboxGroup.toggleOption(...) 完成组内选中值的同步。
Checkbox.Group:多选组与选项配置
Checkbox.Group 用于一组相关的复选选项,提供统一的 value/onChange 管理与"全选、禁用、name"等批量能力。其组件源码为 Group.tsx,通过 index.tsx 中的 Checkbox.Group = Group 挂载为 Checkbox 的复合属性(compound component)。
字符串与对象两种 options 写法
参考 group.tsx,options 既可以是纯字符串/数字数组,也可以是完整的 Option 对象数组:
import { Checkbox } from 'antd';
import type { CheckboxOptionType, GetProp } from 'antd';
const onChange: GetProp<typeof Checkbox.Group, 'onChange'> = (checkedValues) => {
console.log('checked = ', checkedValues);
};
// 方式一:纯字符串
const plainOptions = ['Apple', 'Pear', 'Orange'];
// 方式二:Option 对象数组,可附加 className / style / disabled 等
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']} onChange={onChange} />
<Checkbox.Group options={options} defaultValue={['Pear']} onChange={onChange} />
</>
);
export default App;
对应 Group 源码中 Group.tsx 的 memoizedOptions 逻辑:字符串或数字选项会被自动规约为 { label: option, value: option } 对象,随后逐项渲染为 Checkbox。onChange 回调接收当前被勾选值的数组 checkedValue: T[],排序会尽量与 options 顺序保持一致(源码通过 memoizedOptions.findIndex 排序,见 Group.tsx)。
直接嵌套 Checkbox 子元素的写法
除 options 外,Checkbox.Group 也支持将 <Checkbox value="..."> 直接作为 children 传入。此时 Group 通过 React Context 向子 Checkbox 提供选中值与切换逻辑——Context 定义在 GroupContext.ts,包括 value、disabled、toggleOption、registerValue、cancelValue、name 六个成员。子 Checkbox 挂载时通过 registerValue 注册自身 value、卸载时调用 cancelValue 注销(见 Checkbox.tsx),从而保证即使部分子项在特定条件下不渲染,选中值也能正确维护。
Group 级能力:disabled 与 name
disabled:传入后禁用组内全部复选框。从源码看,子项最终的禁用态为disabled ?? checkboxGroup?.disabled ?? contextDisabled的合并结果(Checkbox.tsx),即优先级为:单项 disabled > Group disabled > ConfigProvider 的 DisabledContext。这也解释了为何官方文档中options对象可单配disabled。name:统一设置组内所有input[type="checkbox"]的name属性,便于表单按组提交与识别。底层在 Checkbox.tsx 中,组内复选框会优先使用checkboxGroup.name。
全选 / 半选联动模式(indeterminate)
在"全选"型 UI 中,父复选框需要表达三种视觉状态:全选(checked)、全不选(未勾选)、以及部分选中(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} />
</>
);
};
这里的核心技巧是:
- 全选:
checkedList.length === plainOptions.length; - 半选:
checkedList.length > 0 && checkedList.length < plainOptions.length; - "全选" Checkbox 的
checked与indeterminate分别绑定上面两个布尔值; - 点击全选时,通过
e.target.checked决定把整组选项写入还是清空。
底层实现上,indeterminate 是一个 DOM 原生属性而非 CSS 状态。在 Checkbox.tsx 中,组件通过 useEffect 将 indeterminate 直接写到内部 input 节点上:checkboxRef.current.input.indeterminate = indeterminate。注意视觉上半选状态的"横线"样式由 style 文件中的 -checkbox-indeterminate 类驱动,且半选态时 DOM 上的 checked 依旧为 false(例如真实 input.checked 仍是 false),因此提交表单时半选框不会被当作已勾选。
与 Grid 布局配合
多选项较多时,可用 Checkbox.Group 与栅格系统 Grid 组合,让每个选项占据固定栅格宽度实现整齐排列。完整代码见 layout.tsx,核心模式是借助 Row/Col 包裹后手动逐个渲染 Checkbox 子项:
<Checkbox.Group style={{ width: '100%' }} onChange={onChange}>
<Row>
<Col span={8}><Checkbox value="A">A</Checkbox></Col>
<Col span={8}><Checkbox value="B">B</Checkbox></Col>
<Col span={8}><Checkbox value="C">C</Checkbox></Col>
</Row>
</Checkbox.Group>
由于 Group 提供 Context,手动分散在 Col 中的 Checkbox 无需任何额外 props 即会自动纳入同一选中值集合,这与"options 数组自动渲染"两种方式可互为替代。
API 详解
官方文档指出 Checkbox 继承 Common props(位于 docs/react),即通用属性均可用。以下按官方 API 表格并结合源码展开。
Checkbox 属性
| Property | Description | Type | Default | Version | 全局配置 |
|---|---|---|---|---|---|
| checked | 是否选中(受控用) | boolean | false | × | |
| classNames | 为组件内部各语义结构自定义类名,支持对象或函数 | Record<SemanticDOM, string> 或 (info: { props }) => Record<SemanticDOM, string> |
- | 6.0.0 | 支持 |
| defaultChecked | 初始选中状态(非受控用) | boolean | false | × | |
| disabled | 是否禁用 | boolean | false | × | |
| indeterminate | 半选状态(见上文全选联动) | boolean | false | × | |
| onChange | 状态变化时的回调 | (e: CheckboxChangeEvent) => void |
- | × | |
| onBlur | 失去焦点时触发 | function() | - | × | |
| onFocus | 获得焦点时触发 | function() | - | × | |
| styles | 为组件内部各语义结构自定义内联样式,支持对象或函数 | Record<SemanticDOM, CSSProperties> 或 (info: { props }) => Record<SemanticDOM, CSSProperties> |
- | 6.0.0 | 支持 |
"全局配置" 列为 ✓ 的属性可由 ConfigProvider 组件级配置 统一覆盖,其中
classNames/styles是 6.0.0 起支持的全局语义化样式配置能力。
从源码 Checkbox.tsx 可确认几个实现细节:
- 受控与非受控共存:通过
useControlledState(defaultChecked, checked)实现;同时存在一个开发环境告警(Checkbox.tsx):当既不在 Group 中又传入了value时,会提示value is not a valid prop, do you mean checked?——因为单个 Checkbox 的语义字段是checked而非value,value只有在 Group 内才作为组选项标识使用。 - 禁用态合并:单项
disabled未定义时自动继承 Group 的 disabled 与全局 DisabledContext(见上节)。 - Wave 点击涟漪:外层包了
<Wave component="Checkbox" ...>(Checkbox.tsx),点击时有 ant-design 特色的涟漪动画;实现位于 _util/wave。 - 事件防冒泡:通过
useBubbleLock锁定 label 与 input 的点击事件,避免点击文本 label 或图标时重复触发 onChange;该 hook 定义在 useBubbleLock.ts。
Checkbox 事件对象
CheckboxChangeEvent 的定义见 Checkbox.tsx,完整结构为:
interface CheckboxChangeEvent {
target: CheckboxChangeEventTarget; // 含 checked 及全部 CheckboxProps
stopPropagation: () => void;
preventDefault: () => void;
nativeEvent: MouseEvent;
}
其中 target.checked 是最常用的取值字段,如 Basic demo 中的 console.log(\checked = ${e.target.checked}`)`。
Checkbox.Group 属性
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| defaultValue | 默认选中值 | (string | number)[] |
[] |
|
| disabled | 禁用组内全部复选框 | boolean | false | |
| name | 所有子项 input[type="checkbox"] 的 name |
string | - | |
| options | 选项配置 | string[] | number[] | Option[] |
[] |
|
| value | 受控选中值 | (string | number | boolean)[] |
[] |
|
| onChange | 勾选变化回调 | (checkedValue: T[]) => void |
- |
其余可透传属性(title、className、style 等)作用于选项元素本身;其中 Option 级 className 自 5.25.0 起支持。从 Group.tsx 源码可确认:Group 内部通过 value/defaultValue 与 useState 维护选中集合,并且当 props 中出现受控 value 时会用 useEffect 同步外部值;若 value 未传入,则由 toggleOption 内部维护 setValue 保持非受控可用。
Option 配置对象
interface Option {
label: string; // 选项文案
value: string; // 选项值
disabled?: boolean; // 可选:仅禁用该项
}
源码 Group.tsx 中的 CheckboxOptionType 在此接口之上还支持 title、className、style、id、onChange、required 等增强字段;同时 AbstractCheckboxGroupProps 支持 HTMLAriaDataAttributes(实现位于 _util/aria-data-attrs.ts),可用于无障碍属性的下发。
方法(Methods)
通过 ref 可调用以下实例能力(Checkbox 的 ref 类型为 CheckboxRef,源自 @rc-component/checkbox,见 Checkbox.tsx 与 index.tsx):
| Name | Description | Version |
|---|---|---|
| blur() | 移除焦点 | |
| focus() | 获取焦点 | |
| nativeElement | 返回 Checkbox 对应的 DOM 节点 | 5.17.3 |
典型用法:
const ref = React.useRef<CheckboxRef>(null);
// 挂载后获取真实 DOM:ref.current?.nativeElement
// 主动聚焦:ref.current?.focus()
<Checkbox ref={ref}>Checkbox</Checkbox>
其中 focus/blur 为 rc-checkbox 提供、向上转发;nativeElement 供需要直接操作原生 DOM(如获取 input、测量尺寸、手动设置 indeterminate)的场景使用。
Semantic DOM:6.0.0 语义化结构与样式定制
自 6.0.0 起,Checkbox 开放了内部语义化 DOM 节点,允许通过 classNames / styles 精确命中内部结构,官方交互预览见 _semantic.tsx,各节点如下:
| 语义节点 | 说明 |
|---|---|
| root | 根元素,即外层的 label.ant-checkbox-wrapper,承载 inline-flex 布局、基线对齐、光标样式与重置样式等基础容器样式 |
| icon | 选中框元素(span.ant-checkbox),承载尺寸、方向、背景色、边框、圆角、过渡动画,以及选中态的勾选标记样式 |
| label | 文本元素(span.ant-checkbox-label),承载文本内边距与距复选框的间距样式 |
代码中 CheckboxSemanticType 的类型定义见 Checkbox.tsx,三者均以 classNames / styles 形式开放,支持对象与函数两种形态(函数接收 { props } 后按条件返回,方便依据 checked/disabled 等状态动态定制)。语义类会通过 useMergeSemantic 与 ConfigProvider 组件级 classNames/styles 自动合并,示例请参考官方 style-class.tsx。
Design Token
Checkbox 的全部设计变量(尺寸、间距、选中色、动画时长等)由 <ComponentTokenTable component="Checkbox"> 自动生成于官方文档,令牌计算与类型来源可追溯至主题模块 components/theme 与样式实现 components/checkbox/style;如需统一微调全局 checkbox 视觉,可通过 ConfigProvider 的 theme 覆盖对应 token。
在 Form 中使用的关键 FAQ
官方 FAQ 记录了最常见的一个误区:"为什么 Checkbox 在 Form.Item 中不生效?"
原因是 Form.Item 默认把表单值绑定到子组件的 value 属性上,而 Checkbox 表示勾选状态的属性是 checked 而不是 value(value 仅作为 Group 内部选项标识,见上文告警逻辑)。解决方式是使用 valuePropName 将绑定属性改为 checked:
<Form.Item name="fieldA" valuePropName="checked">
<Checkbox />
</Form.Item>
此时 Form 的 setFieldsValue / initialValues 等数据流都会正确读写 checked。另外从源码 Checkbox.tsx 可看到,处于 Form.Item 中的 Checkbox 根节点会自动追加 -wrapper-in-form-item 类(通过读取 Form 上下文 的 FormItemInputContext 判定),用于校验错误提示等场景下的样式适配。若还需控制"未勾选时同样提交值",可配合 getValueProps 或自行用 onChange 维护 false 值。
设计 Token 与无障碍细节补充
除了文档表格内的属性,从 Checkbox.tsx 渲染结构还可归纳以下值得注意的实践要点:
- 原生语义:最终渲染为
<label>+ 内部<RcCheckbox>(原生input[type="checkbox"])+ 可选<span>文本,天然支持键盘操作与无障碍树。 - Group 的 role:
Checkbox.Group根节点默认role="group"(Group.tsx),便于读屏器理解选项分组关系。 - title / tooltip:若需在禁用态显示说明,可结合 Tooltip 或 Popover 包裹,官方亦提供了对应 debug 示例 debug-disable-popover.tsx 与同宽对齐参考 debug-group-width.tsx。
总结
Checkbox 组件看似简单,实则内含一整套精密的受控/非受控、Context 分组、禁用态继承与语义化样式体系。回顾全文要点:
- 单个使用时把握
checked/defaultChecked与onChange的受控语义,注意value在非 Group 场景会被告警提示; Checkbox.Group通过 Context 统一管理value集合,options支持字符串与Option对象两种形态,禁用态优先级为"单项 > Group > DisabledContext";- 全选联动利用
indeterminateDOM 原生属性实现半选态,注意半选时checked仍为 false; - 6.0.0 起可基于
root/icon/label语义节点用classNames/styles做精细化定制; - Form 集成必须使用
valuePropName="checked"完成值绑定。
希望读者结合本文引用的源码与 demo 路径深入阅读,从而在真实业务中游刃有余地运用 Checkbox 及其多选组能力。
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