首页
/ antd Checkbox 禁用态(Disabled)深入解析:从 Demo 到源码的完整实践指南

antd Checkbox 禁用态(Disabled)深入解析:从 Demo 到源码的完整实践指南

2026-09-06 18:40:34作者:胡易黎Nicole

本指南围绕 ant-design 仓库中 Checkbox 组件的 Disabled 示例文档 展开,讲解如何让单个或整组复选框进入不可用状态、三种典型禁用形态(未选、半选、已选)的呈现差异,并下沉到 disabled 属性合并优先级、ConfigProvider 全局禁用上下文与禁用态样式 Token 的源码实现。读完你可以直接照抄示例代码完成「禁用复选框」场景,同时理解禁用态背后从 prop 到 class、再到主题 Token 的完整渲染链路。

示例文档与运行效果:一屏演示三种禁用形态

在仓库 components/checkbox/demo/disabled.tsx 中,通过一个纵向 Flex 容器罗列了三个禁用复选框:

import React from 'react';
import { Checkbox, Flex } from 'antd';

const App: React.FC = () => (
  <Flex vertical gap="medium">
    <Checkbox defaultChecked={false} disabled />
    <Checkbox indeterminate disabled />
    <Checkbox defaultChecked disabled />
  </Flex>
);

export default App;

与之配套的文档页 components/checkbox/demo/disabled.md 仅用一句话点明主题(zh-CN:checkbox 不可用;en-US:Disabled checkbox.),因此理解这个示例的关键在于解读三个复选框背后的状态组合:

复选框 关键属性 视觉语义
第 1 个 defaultChecked={false} + disabled 未选中的禁用复选框(默认形态)
第 2 个 indeterminate + disabled 半选(不确定态)的禁用复选框
第 3 个 defaultChecked + disabled 已选中的禁用复选框

三点值得注意:

  • 三个复选框都没有 checked 受控属性,说明本示例演示的是非受控 + 禁用的组合;禁用后用户点击也不会触发内部状态更新,因此 defaultChecked 的初始值会被完整保留。
  • indeterminate 属于「外观态」,它并不表示第三个勾选状态,只负责渲染一横线的半选图形;与 disabled 叠加后仍以禁用配色呈现。
  • 组件的渲染快照(见 demo.test.tsx 快照 中对应片段)显示,三个禁用项分别渲染出 ant-checkbox-wrapper-disabledant-checkbox-indeterminateant-checkbox-checked 等 class 组合,<input> 上都带有原生 disabled 属性。

API 入口:Checkbox 与 Checkbox.Group 的禁用配置

单个 Checkbox 的 disabled

组件 components/checkbox/index.en-US.md 的 API 表格给出了单选复选框的核心属性:disabled(If disable checkbox,boolean,默认 false)。此外本示例用到的相关属性还包括:

属性 说明 默认值
checked 是否勾选(受控) false
defaultChecked 初始勾选状态(非受控) false
indeterminate 半选状态,仅影响外观 false
disabled 是否禁用 false

这些 props 的 TypeScript 定义位于 Checkbox.tsxAbstractCheckboxProps,其中 disabled?: booleandefaultChecked?: boolean 均为可选属性。

Checkbox.Group 的两个禁用粒度

对于整组场景,Checkbox.Group 提供了两个层面的禁用入口(见 Group.tsxindex.en-US.md 的 Group API 表):

  • 组级禁用<Checkbox.Group disabled> —— 一键让组内所有复选框不可用,无需逐个设置。
  • 选项级禁用:仅在使用 options 声明式定义时生效,Option 对象中携带独立的 disabled 字段:
interface Option {
  label: string;
  value: string;
  disabled?: boolean;
}

这一接口在 Group.tsx 中被扩展为 CheckboxOptionType,还支持 titleclassName(5.25.0+)、styleonChangerequired 等字段。渲染时逐项处理禁用:

<Checkbox
  disabled={'disabled' in option ? option.disabled : restProps.disabled}
  ...
>

选项自身声明了 disabled 时以选项为准,否则回退到 Group 的 disabled

源码剖析:disabled 是如何被合并与生效的

三级合并优先级:自身 prop > 组上下文 > ConfigProvider

Checkbox.tsx 中,禁用状态并不只是读取一个 prop:

const { isFormItemInput } = React.useContext(FormItemInputContext);
const contextDisabled = React.useContext(DisabledContext);
const mergedDisabled = disabled ?? checkboxGroup?.disabled ?? contextDisabled;

由此可以推断出禁用态的合并顺序为:

  1. Checkbox 自身的 disabled prop 优先级最高;
  2. 其次取 checkboxGroup?.disabled,即来自 Checkbox.Group 的组级禁用,它通过 GroupContext 在组内传递;
  3. 最后回退到 DisabledContext,这是由 ConfigProvider 提供的全局禁用上下文

全局禁用层的实现位于 config-provider/DisabledContext.tsxDisabledContextProvider 读取外层值并在自身未声明 disabled 时继续透传外层值(disabled ?? originDisabled)。也就是说,在 ConfigProvider 上开启禁用后,不显式写 disabled 的 Checkbox 也会被统一禁用,适合「整表只读」「表单提交中锁输入」等场景。

禁用态落到了哪里:DOM class 与原生 input

mergedDisabled 计算完成后,在 Checkbox.tsx 中被用于拼接两个关键 class:

  • wrapper 层:${prefixCls}-wrapper-disabled(即 ant-checkbox-wrapper-disabled);
  • 图标层:内部传入的 disabled 会让底层 RcCheckbox 渲染出 ant-checkbox-disabled,并给原生 <input type="checkbox"> 加上 disabled 属性。

同时组件被 <Wave> 包裹,渲染段 传入 disabled={mergedDisabled},用于禁用点击时由 antd Wave 产生的涟漪反馈

禁用态样式:光标与配色 Token

禁用态的样式定义集中在 components/checkbox/style/index.ts,要点包括:

  • wrapper 禁用时 cursor: not-allowed
  • checkbox 及其原生 input 除 cursor: not-allowed 外还会设置 pointerEvents: none。源码注释说明(对应 issue 场景 #39822):关闭原生 input 的指针事件,是为了让外层容器(如 Tooltip)仍能正常接收并触发事件,即「禁用后仍可提示为什么禁用」;
  • 配色全部走主题 Token,保证与整体主题联动:
    • 背景 token.colorBgContainerDisabled
    • 边框 token.colorBorder
    • 勾选对勾(:after 边框)与文字(& + span)使用 token.colorTextDisabled
    • 半选态横线(&${checkboxCls}-indeterminate::after)使用 token.colorTextDisabled

因此禁用 Checkbox 与已勾选/半选状态叠加时,勾号与横线都会统一变灰,而不是只对「未选」形态生效——这正是本示例三行复选框视觉统一的底层原因。由于禁用与 hover 相关规则互斥(样式中的 :hover 选择器都限定在 :not(...-disabled) 范围内),禁用项在悬浮时也不会出现主题色描边或主色填充变化。

测试验证:禁用态在渲染层的行为

仓库为该 demo 提供了自动化验证。快照文件 demo.test.tsx.snapdemo-extend.test.ts.snap 中记录了 renders components/checkbox/demo/disabled.tsx 的完整输出,可以核对到:

  • 外层为 ant-flex ant-flex-vertical ant-flex-gap-medium 容器;
  • 三个 <label> 均带 ant-checkbox-wrapper-disabled
  • 中间一项的 icon 同时带 ant-checkbox-indeterminate,第三项带 ant-checkbox-checked
  • 每个 <input> 上都有 disabled 属性且未被 checked 属性污染(未选项不带 checked,已选项带 checked)。

这些快照由 demo.test.tsxdemo-extend.test.tsx 生成,可作为「禁用的语义 class 与原生 input 属性正确下发」的回归证据;组件单元测试(checkbox.test.tsxgroup.test.tsx)进一步覆盖了禁用交互、Group 级禁用与选项级禁用等行为。

常见叠加场景与注意事项

  • 表单中禁用:Form.Item 默认把值绑定到 value,而 Checkbox 的状态字段是 checked,需通过 valuePropName="checked" 绑定(见 index.en-US.md 的 FAQ)。对禁用项而言,提交时其值是否包含在表单值中,取决于 Form 收集逻辑,而非禁用本身。
  • 禁用 + 受控:若同时传了 checkeddisabled,禁用只是阻止用户交互;受控值仍可通过上层状态改变,useControlledState(见 Checkbox.tsx)确保外部 checked 始终优先。
  • 禁用 + Tooltip:由于 disabled 时原生 input 关闭了指针事件但外层 label 仍可捕获事件,开发者可以在 Checkbox 外部包一层 Tooltip 实现「悬停解释禁用原因」的交互(仓库中还提供了该场景的调试示例 debug-disable-popover.tsx)。
  • 全局禁用:通过 ConfigProvider 注入的 DisabledContext,可对子树内所有 Checkbox(乃至其他支持该上下文的组件)一键禁用,适合表格只读与批量锁定场景。
  • 样式覆盖:若需自定义禁用配色,优先在 ConfigProvider 主题中调整 colorBgContainerDisabledcolorTextDisabled 等全局 Token;Checkbox 组件自身没有额外的禁用专项 ComponentToken,其禁用视觉完全由上述全局 Token 与通用边框 Token 推导而来(见 style/index.tsCheckboxToken 仅含 checkboxSizecheckboxCls 可佐证)。

小结

「禁用复选框」虽然是 Checkbox 的一个小状态,但完整的支持横跨多个层次:单个 Checkboxdisabled prop、Checkbox.Group 的组级与选项级 disabledConfigProvider 的全局禁用上下文,以及最终映射到 ant-checkbox-wrapper-disabled / ant-checkbox-disabled class 与一组禁用主题 Token 的样式体系。理解 disabled.tsx 这短短十几行代码,就能同时掌握 antd 的禁用态优先级规则、非受控初始值行为以及如何用一套 Token 保持禁用视觉与主题一致,可直接复用到表单锁定、只读列表、批量操作受限等真实业务场景。

登录后查看全文
热门项目推荐
相关项目推荐