Ant Design Cascader 选项禁用完全指南:通过 options 的 `disabled` 字段控制可选状态与样式实现
Cascader(级联选择)常用于省市区、组织层级等多级联动数据选择,而在真实业务中,某些层级节点(例如已停用的地区、无权限的组织、仅供展示的分类)必须禁止被选中。本指南以 ant-design 仓库中 disabled-option 示例文档 为切入点,完整讲解如何通过 options 数据中的 disabled 字段禁用单个级联选项,并结合组件源码与测试,剖析禁用态在交互、多选勾选、搜索与样式层面上的真实表现。读完本文,你将掌握单选项禁用与整组件禁用的边界、多级选项树的禁用粒度,以及如何定制禁用态样式。
从一个最小示例看懂 disabled 字段
在 Cascader 中,禁用某个选项的方式极其简单:在 options 数据对应节点上标记 disabled: true。官方示例文档给出了一句最精炼的概括:
Disable option by specifying the
disabledproperty inoptions. / 通过指定 options 里的disabled字段。
这句话对应的可运行代码位于 components/cascader/demo/disabled-option.tsx,它定义了一棵「省 / 市 / 景点」三级选项树,其中第二个省 jiangsu 被标记为禁用:
import React from 'react';
import type { CascaderProps } from 'antd';
import { Cascader } from 'antd';
interface Option {
value: string;
label: string;
disabled?: boolean;
children?: Option[];
}
const options: Option[] = [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{
value: 'xihu',
label: 'West Lake',
},
],
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
disabled: true, // 本节点被禁用
children: [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
},
],
},
],
},
];
const onChange: CascaderProps<Option>['onChange'] = (value) => {
console.log(value);
};
const App: React.FC = () => <Cascader options={options} onChange={onChange} />;
export default App;
这段代码与 <Cascader options={options} onChange={onChange} /> 的基础用法完全一致——禁用并不需要额外新增任何 props,一切由选项数据驱动。示例把演示文档(.md)与可运行源码(.tsx)分离存放:.md 只保留一句说明,.tsx 承载完整逻辑,二者通过组件文档首页的 <code src="./demo/disabled-option.tsx">Disabled option</code> 语法被组装进 Cascader 组件文档的示例区。
Option 数据模型:disabled 在选项类型中的位置
要正确使用 disabled,需要先理解 Cascader 的选项数据结构。Cascader 组件文档 中给出了官方 Option 类型定义:
interface Option {
value: string | number;
label?: React.ReactNode;
disabled?: boolean;
children?: Option[];
// Determines if this is a leaf node(effective when `loadData` is specified).
// `false` will force trade TreeNode as a parent node.
// Show expand icon even if the current node has no children.
isLeaf?: boolean;
}
几个容易踩坑的细节:
disabled是可选布尔字段,缺省即为「可选」,因此只需在需要禁用的节点上显式声明,无需为每个节点补false。- 禁用粒度是「节点级」的:它可以出现在任意层级的节点上——既可以是叶子节点,也可以是仍带着
children的中间节点(如示例中带子级的jiangsu)。标记为disabled只影响该节点自身是否可被选中。 - 字段名固定为
disabled:与label、value等不同,fieldNames自定义字段名能力 在文档中仅覆盖label、value、children三项,disabled不在其重命名范围内。 - 该接口是 TypeScript 可选成员,因此把
options声明为带类型参数的数据时,推荐像示例那样定义interface Option { disabled?: boolean },从而获得完整的编译期提示。
在 antd 的导出体系中,这个选项类型进一步泛化为 DefaultOptionType / BaseOptionType 并随组件一并导出(参见 index.tsx 的类型导出),这也意味着基于 CascaderProps<Option> 泛型书写的 onChange、onSearch 等回调都能自动获得 disabled 字段的类型感知。
两个易混淆的禁用概念:禁用「选项」vs 禁用「整个选择器」
初学者经常把「禁用某个选项」与「禁用整个级联选择器」混为一谈,二者在 antd 中是两套完全不同的机制:
- 逐项禁用(本文主题):写在
options数据里,作用于下拉面板内的某一条目,由底层级联实现(@rc-component/cascader)处理,视觉上表现为该条目置灰、不可选中。 - 整体禁用:通过组件级
disabled?: boolean属性(默认false)实现,作用于整个输入框,效果是点击无反应、整个控件不可用。
有意思的是,组件级 disabled 并非简单读取一个 prop。查看 Cascader 主实现,可以看到它从 config-provider 的 DisabledContext 中读取上下文合并:
// ===================== Disabled =====================
const disabled = React.useContext(DisabledContext);
const mergedDisabled = customDisabled ?? disabled;
也就是说,即便你不写 disabled,只要外层套了 <ConfigProvider componentDisabled>,整个 Cascader 也会被批量禁用;最终合并结果通过 disabled={mergedDisabled} 传入底层组件(index.tsx#L473)。面板形态的 CascaderPanel 采用同样的 DisabledContext 合并策略,保证两种形态行为一致。
而在选项数据中标记 disabled: true 则完全走另一条链路:数据随 options 进入底层级联树,逐节点决定「该项可否被选择」。二者互不替代——整体禁用是开关整扇门,逐项禁用是锁住房间里的某几个抽屉。实际开发中可组合使用,例如表格详情页先整体禁用以展示只读数据,同时选项里仍保留历史节点的禁用标记。
禁用态的交互行为与视觉效果
一个节点被标为 disabled 后,antd 会同时从「样式」与「交互」两个层面处理它。
样式层面:禁用条目的专用 class 与 token
在组件样式层,禁用条目拥有独立的规则。查看 级联列样式 中的实现:
'&-disabled': {
color: token.colorTextDisabled,
cursor: 'not-allowed',
'&:hover': {
background: 'transparent',
},
[iconCls]: {
color: token.colorTextDisabled,
},
},
即渲染时下拉条目会获得 ant-cascader-menu-item-disabled 类名,并应用:
- 文字颜色变为主题禁用色
colorTextDisabled; - 鼠标指针显示为
not-allowed(禁止符号); - hover 不再出现高亮背景(正常条目 hover 会显示
controlItemBgHover); - 展开箭头 / loading 图标同步置灰。
同时,选中态高亮(-active)规则显式排除了禁用条目,columns.ts#L94-L100 中使用了 &-active:not(...-disabled) 的选择器,保证即使某条数据异常带有选中态,禁用条目也永远不会出现「选中高亮 + 禁用置灰」的自相矛盾效果。以上样式引用的颜色均来自主题 token,因此若想统一微调配色,直接修改主题变量即可,无需覆盖 CSS。
交互层面:不可选中、不可勾选
从组件快照可以确证禁用条目被完整地以禁用态渲染。在 demo-extend 测试快照 中,jiangsu 节点对应的渲染结果为:
<li
aria-checked="false"
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-disabled"
data-path-key="jiangsu"
role="menuitemcheckbox"
title="Jiangsu"
>
可以看到它同时携带 -expand(因带子节点而有展开指示)与 -disabled 两个类名。这份快照也透露出两个信息:
- 一个带
children的禁用节点并不会因为禁用而被从树中剔除,其子级结构依旧保留在数据模型中,是否继续下钻取决于底层树组件对「非叶子节点禁用」的处理约定; - 面板中每个选项以
role="menuitemcheckbox"的可勾选语义呈现,而禁用项在交互上会被底层级联实现屏蔽选中。
多选(multiple)场景:checkbox 一起禁用
在 multiple 多选模式下,禁用语义会传导到选项前的复选框。级联测试 覆盖了这一行为:禁用项对应的复选框会带上 .ant-cascader-checkbox-disabled 类名,并且当用户勾选某个「父级」复选框时,只会连带选中其下未被禁用的子项(测试注释原文为 "Check all children except disableCheckbox When the parent checkbox is checked")。这意味着即便整棵子树被批量勾选,被禁用的那一个也会被自动跳过,不会出现「禁用项被间接选中」的脏数据。
搜索与空状态中的禁用
还有两个容易被忽略的禁用细节:
- 空数据条目也是禁用的:当
options为空、下拉展示notFoundContent(默认 "No data")时,该空提示项同样以.ant-cascader-menu-item-disabled渲染,测试 index.test.tsx#L350-L353 专门校验了这一点,保证空提示不会被误当成可选项。 - 样式层对空菜单有专门处理:当菜单为空时整列条目的
color直接使用colorTextDisabled(columns.ts#L38-L47),与禁用条目视觉统一。
如何验证与调试:仓库内测试设施
antd 对每个组件都配有层层测试,理解测试结构可以帮你快速验证自己对 disabled 行为的假设:
- Demo 级测试: demo.test.tsx 通过
demoTest('cascader', …)遍历渲染所有 demo(包括 disabled-option),并断言无运行时错误与多余告警,同时rootPropsTest校验根节点属性。也就是说,官方所有示例代码都持续处于可运行状态。 - 快照级测试:demo-extend 快照(见上文引用的 demo-extend.test.ts.snap)会捕获
disabled选项的实际 DOM 输出,是观察禁用条目最终 class 与 aria 属性的最快途径。 - 行为级测试: index.test.tsx 中关于禁用复选框、空内容禁用、多选跳过禁用子项等用例,直接对应真实用户操作。
如果你在业务中遇到「禁用不生效」或「禁用项仍被选中」等问题,可以按下列顺序自查:
- 确认
disabled写在了正确的节点层级上(写在options的节点对象内,而不是<Cascader>的 props 上); - 确认数据通过
options传入且字段名确实是disabled(未做错误的字段重命名); - 确认没有在外层误用组件级
disabled/ConfigProvider componentDisabled把整个选择器关掉; - 在浏览器中检查下拉项是否带上了
ant-cascader-menu-item-disabled类名,以此区分是「数据未生效」还是「样式被覆盖」。
小结
disabled 是 Cascader options 节点上最简单也最常用的开关之一:在 disabled-option 示例 中,它仅需一行 disabled: true 即可让任意层级的选项进入不可选中状态。但在 antd 的实现中,这背后是由类型定义、底层级联树交互、主题 token 样式与覆盖多选/搜索/空态的完整行为体系共同支撑的。理解「选项级禁用」与「控件级禁用」两条边界、掌握 .ant-cascader-menu-item-disabled 类与 colorTextDisabled token 的定制入口,再借助仓库内 demo 快照与行为测试来验证,你就能在省市区、组织树等各类多级数据选择场景中精准控制每个节点的可选性。
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