ant-design Checkbox.Group 数组驱动:用 options 配置优雅生成复选组
导读
本篇文章以 ant-design 官方 Demo「Checkbox Group(group.tsx)」为蓝本,系统讲解 Checkbox.Group 的 数组驱动(array-driven) 用法:只用一个 options 数组,即可一次性渲染出多个复选项,并自动完成勾选状态同步、受控与非受控切换、全组禁用、单项禁用等行为。读完你将掌握 options 的字符串/对象两种形态、onChange 回调结果顺序规律、与原生 <Checkbox> 子元素写法的差异,并能从源码层面理解 Checkbox.Group 内部如何基于 GroupContext 与 toggleOption 维护整组状态。
Demo 概述:用数组生成一组 Checkbox
Checkbox.Group 解决的是这样一个高频场景:选项来自一组数据(例如接口返回的标签列表),你不再需要手写一堆 <Checkbox value="..."> 再逐个绑定状态,而是直接传入数据源,让组件替你完成遍历与渲染。官方 Demo 的说明非常凝练:
方便的从数组生成 Checkbox 组。Generate a group of checkboxes from an array.
对应的完整示例代码见 components/checkbox/demo/group.tsx,该示例在 index.en-US.md 中以 <code src="./demo/group.tsx">Checkbox Group</code> 的形式被文档引用展示。
最小示例:纯字符串数组
最直接的用法是传入 string[],每个元素既是显示文案也是取值:
import React from 'react';
import { Checkbox } from 'antd';
import type { GetProp } from 'antd';
const onChange: GetProp<typeof Checkbox.Group, 'onChange'> = (checkedValues) => {
console.log('checked = ', checkedValues);
};
const plainOptions = ['Apple', 'Pear', 'Orange'];
const App: React.FC = () => (
<Checkbox.Group options={plainOptions} defaultValue={['Apple']} onChange={onChange} />
);
export default App;
要点:
options={plainOptions}传入三个字符串,Checkbox.Group会渲染出三枚复选组件;defaultValue={['Apple']}声明初始勾选项,属于非受控用法;onChange回调接收checkedValues,即当前被勾选 value 的数组,如上例首屏应为['Apple'],用户勾选 "Pear" 后变为['Apple', 'Pear']。
官方类型 GetProp<typeof Checkbox.Group, 'onChange'> 可帮你推导出回调参数的准确类型,避免手写 (checkedValues: (string | number | boolean)[]) => void。
对象数组:label / value / className / disabled
当文案与取值不同、或需要对单项做定制时,可改用 CheckboxOptionType<T>[] 对象数组。Demo 中展示了带自定义 className 的选项:
import React from 'react';
import { Checkbox } from 'antd';
import type { CheckboxOptionType, GetProp } from 'antd';
const onChange: GetProp<typeof Checkbox.Group, 'onChange'> = (checkedValues) => {
console.log('checked = ', checkedValues);
};
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={options} defaultValue={['Pear']} onChange={onChange} />
);
export default App;
对象选项除 label、value 外还支持多项扩展字段。完整定义见 Group.tsx 中的 CheckboxOptionType<T> 接口:
| 字段 | 类型 | 说明 |
|---|---|---|
label |
React.ReactNode |
显示在勾选框右侧的内容,可以是任意 React 节点 |
value |
T |
该项的唯一取值,参与状态同步与 onChange 输出 |
disabled |
boolean |
仅禁用当前选项 |
style |
React.CSSProperties |
单项根元素的行内样式 |
className |
string |
单项根元素的自定义类名,5.25.0+ 支持 |
title |
string |
选项的 title 属性 |
id |
string |
单项 checkbox 的 id |
onChange |
(e: CheckboxChangeEvent) => void |
单项自己的变更回调 |
required |
boolean |
标记必填(用于表单场景的 HTML 校验) |
className、style 等单项配置在 Group.tsx 渲染每个 <Checkbox> 时逐一透传:外层拼接了 ${groupPrefixCls}-item,例如最终根元素类名为 ant-checkbox-group-item label-1。
全组禁用与单项禁用
Demo 第三段演示了「全组禁用 + 单项覆盖」的组合场景:
const optionsWithDisabled: CheckboxOptionType<string>[] = [
{ label: 'Apple', value: 'Apple', className: 'label-1' },
{ label: 'Pear', value: 'Pear', className: 'label-2' },
{ label: 'Orange', value: 'Orange', className: 'label-3', disabled: false },
];
// 组级 disabled 会一次性禁用所有项
<Checkbox.Group
options={optionsWithDisabled}
disabled
defaultValue={['Apple']}
onChange={onChange}
/>
这里的两种 disabled 语义要注意区分:
- 组级
disabled:Checkbox.Group上的disabled会把整组所有项禁用,此时点击任一 checkbox 都不会触发任何onChange; - 单项
disabled:写在具体 option 对象上的disabled,只影响当前项;如果组未禁用,用户仍可勾选组内其他项。
在源码中,单项的禁用值合并逻辑为 'disabled' in option ? option.disabled : restProps.disabled(见 Group.tsx),即选项自身优先、否则回退到组级配置;再往下 Checkbox.tsx 还会与 ConfigProvider 的 componentDisabled 做第三级合并:disabled ?? checkboxGroup?.disabled ?? contextDisabled。
该行为在测试 components/checkbox/tests/group.test.tsx 中被直接验证:组禁用时 onChangeGroup 完全不触发;组未禁用但单项禁用时,点击其他项回调照常触发并只输出被勾选值。此外还覆盖了一个边界场景——当外层 ConfigProvider componentDisabled 生效时,通过 <Checkbox.Group disabled={false}> 可以显式解除组内复选项的禁用状态。
Checkbox.Group API 速查
结合 index.en-US.md 的官方 API 表与源码 CheckboxGroupProps(见 Group.tsx),Checkbox.Group 的核心参数如下:
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
options |
选项数据源,字符串/数字或对象数组 | string[] | number[] | Option[] |
[] |
value |
受控用法下当前选中值集合 | (string | number | boolean)[] |
- |
defaultValue |
非受控用法下的默认选中集合 | (string | number)[] |
[] |
onChange |
勾选变化时回调,参数为选中值数组 | (checkedValue: T[]) => void |
- |
disabled |
是否禁用整组 | boolean |
false |
name |
应用到组内所有 input[type="checkbox"] 的 name |
string |
- |
className / style / rootClassName |
组容器样式定制 | - | - |
几点值得展开的细节:
- 受控与非受控:源码通过
restProps.value || defaultValue || []初始化 state(Group.tsx),并在'value' in restProps时用useEffect同步外部传入的value(Group.tsx)。也就是说,传了value就是受控组件,勾选操作通过toggleOption计算新值后仅回调onChange而不直接改内部状态(Group.tsx);不传value时则由内部 state 自行维护。 - onChange 输出顺序是稳定的:回调参数并非按点击先后排列,而是会先过滤掉未注册的值,再按选项在
options中的出现顺序排序(Group.tsx),这保证了同样一组勾选在任意点击顺序下都会得到一致的结果,方便与服务端提交、断言测试对齐。 - onChange 只输出“已注册”的值:状态数组中可能残留历史选项,
registerValue/cancelValue机制(见 GroupContext.ts)让每个Checkbox在挂载/卸载时向组注册或注销自己的 value,回调输出前会过滤掉未注册项(相关 issue 见 Group.tsx 的注释引用)。 - name 组级透传:
Checkbox.Group上设置name后,组内所有原生 checkbox input 都会拿到该 name,测试 group.test.tsx 对此有断言;此外组容器默认带有role="group"(Group.tsx),便于无障碍语义表达。
数组写法 vs 子元素写法
options 并非唯一的选择。Checkbox.Group 同样支持直接嵌套 <Checkbox value="..."> 子元素,两条路径在 Group.tsx 中合流:
<Checkbox.Group defaultValue={['A']} onChange={onChange}>
<Checkbox value="A">Option A</Checkbox>
<Checkbox value="B">Option B</Checkbox>
<Checkbox value="C">Option C</Checkbox>
</Checkbox.Group>
二者的取舍可以这样判断:
- 数据驱动优先用
options:当选项来自列表、接口或需要渲染大量同构项时,options一行声明即完成生成,代码量与维护成本最低,也正是本 Demo 的主题; - JSX 需要精细化定制时用子元素:当每项需要嵌入富文本、图标或差异化的自定义渲染时,直接书写
<Checkbox>子元素更灵活。
需要留意的是,直接以子元素方式使用时,onChange 回调同样遵循上述“已注册 value + 按出现顺序排序”的规律。子元素写法的选值/注册链路与 options 写法完全一致:子级 Checkbox 在 Checkbox.tsx 中通过 checkboxGroup.value.includes(value) 判定勾选态,并在挂载时调用 registerValue;点击时通过 onInternalChange(Checkbox.tsx)调用 checkboxGroup.toggleOption({ label: children, value }) 完成整组状态更新。
还有一个实用细节:若某个 Checkbox 需要脱离组管理(自己维护勾选态、不参与整组状态),可为其设置 skipGroup 属性,此时该子项会跳过 group 的 toggleOption 注册与受控合并逻辑(见 Checkbox.tsx 与 Checkbox.tsx)。
小结
从本 Demo 出发可以看到,Checkbox.Group 用数组驱动把「多选场景」压缩成了三个核心要素:options(数据)、defaultValue/value(状态)、onChange(回调)。对象选项在 label/value 之外还提供 className、disabled、style、title、id、onChange、required 等扩展能力,配合组级 disabled 可以精确控制任意粒度的禁用范围;其内部由 GroupContext 完成跨子项的状态广播,输出顺序稳定且始终只包含当前渲染中的合法值。
如果需要在真实页面中组合使用,建议把上面的代码原样放入 React 项目即可运行,并注意:value 用于受控、defaultValue 用于非受控,二者不要混用。需要统一外部禁用状态时,可优先通过 ConfigProvider 的 componentDisabled 配合 Checkbox.Group disabled={false} 实现局部覆盖。
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 StartedRust0623
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