首页
/ ant-design Checkbox 多选框组件完全指南:从基础用法、分组全选到表单集成与语义化定制

ant-design Checkbox 多选框组件完全指南:从基础用法、分组全选到表单集成与语义化定制

2026-09-06 18:44:22作者:翟江哲Frasier

Checkbox 是 ant-design(组件总目录)中负责"多项选择收集"的数据录入组件。本文以该组件的官方中文文档为骨架,结合仓库内的真实源码(Checkbox.tsxGroup.tsx)与示例代码,带你全面掌握独立多选框、Checkbox.Group 分组、全选/半选(indeterminate)、在 Form.Item 中的绑定方式,以及 6.0.0 新增的 Semantic DOM 语义化定制能力。读完你将能够在真实业务中正确选择受控/非受控模式、构造可复用的分组选择逻辑,并在需要时直接修改组件内部任意结构单元的样式。

何时使用

根据官方文档,Checkbox 适用于两类场景:

  • 在一组可选项中进行多项选择时;
  • 单独使用时表示两种状态之间的切换,此时它和 switch 类似,但两者语义不同:切换 switch 会直接触发状态改变;而 checkbox 一般用于状态标记,通常需要与提交操作配合(例如"我已阅读并同意协议"这类勾选确认)。

一句话区分:多选场景优先考虑 Checkbox.Group,二选一且需要立即生效的动作使用 switch,二选一但仅作为待提交状态标记则使用单个 Checkbox

从演示出发:六类典型场景

组件目录(components/checkbox/demo)中提供了丰富的可运行示例,其中正式演示(非 debug)包含:

此外还有若干 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 会把自身的 disabledname 通过 Context 传递给内部每一个 Checkbox(见 Checkbox.tsxcheckboxGroup.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 详解

通用属性(如 classNamestyle、无障碍属性等)请参考 通用属性文档。以下为 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.tsxuseComponentConfig('checkbox') 读取的上下文有关:目前组件会从全局上下文合并 className/style/classNames/styles,但 checkeddisabled 等行为型属性仍以组件自身 props 为准。

CheckboxChangeEvent 的结构在源码中有明确类型定义(Checkbox.tsx):

interface CheckboxChangeEvent {
  target: CheckboxChangeEventTarget; // 含 checked: boolean
  stopPropagation: () => void;
  preventDefault: () => void;
  nativeEvent: MouseEvent;
}

disabled 的合并优先级值得注意:源码中 mergedDisabled = disabled ?? checkboxGroup?.disabled ?? contextDisabledCheckbox.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 还包括 styleclassName(5.25.0+)、titleidonChangerequired 等字段,且 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 计算(如 colorBgContainercolorBordercolorPrimarycolorPrimaryHovercheckboxSize 等),并支持 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(含 checkeddisabledindeterminate),因此可以轻松实现"选中态换肤"等动态样式;对象/函数形式同样适用于 classNamesstyles,且两者会与 ConfigProvider 上下文中注入的全局 classNames/styles 做合并。此外,复选框还保留了 -wrapper-checked-wrapper-disabled 等状态修饰类,以及供自定义样式使用的语义化类前缀。

主题变量(Design Token)

Checkbox 的样式完全由 CSS-in-JS 的 token 驱动,主要受以下全局 Design Token 影响(均为 antd 主题体系标准 token,来源见 style/index.ts):

  • colorPrimary / colorPrimaryHover:选中态底色、边框与 hover 反馈色;
  • colorBgContainercolorBordercolorWhite:选框底色、未选中边框色与对勾颜色;
  • borderRadiusSM:选框圆角;
  • checkboxSizelineWidthlineWidthBold:选框尺寸与线条粗细;
  • paddingXS:选框与文本间距;
  • marginXS:Group 内选项的列间距;
  • motionDurationSlow / motionDurationMid / motionDurationFastmotionEaseOutBack / motionEaseInBack:勾选动画时长与缓动。

如需整体换肤,推荐通过 ConfigProvidertheme 修改这些 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 层做全局主题定制。
登录后查看全文
热门项目推荐
相关项目推荐