首页
/ Ant Design Cascader 选项禁用完全指南:通过 options 的 `disabled` 字段控制可选状态与样式实现

Ant Design Cascader 选项禁用完全指南:通过 options 的 `disabled` 字段控制可选状态与样式实现

2026-09-06 18:21:49作者:管翌锬

Cascader(级联选择)常用于省市区、组织层级等多级联动数据选择,而在真实业务中,某些层级节点(例如已停用的地区、无权限的组织、仅供展示的分类)必须禁止被选中。本指南以 ant-design 仓库中 disabled-option 示例文档 为切入点,完整讲解如何通过 options 数据中的 disabled 字段禁用单个级联选项,并结合组件源码与测试,剖析禁用态在交互、多选勾选、搜索与样式层面上的真实表现。读完本文,你将掌握单选项禁用与整组件禁用的边界、多级选项树的禁用粒度,以及如何定制禁用态样式。

从一个最小示例看懂 disabled 字段

在 Cascader 中,禁用某个选项的方式极其简单:options 数据对应节点上标记 disabled: true。官方示例文档给出了一句最精炼的概括:

Disable option by specifying the disabled property in options. / 通过指定 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:与 labelvalue 等不同,fieldNames 自定义字段名能力 在文档中仅覆盖 labelvaluechildren 三项,disabled 不在其重命名范围内。
  • 该接口是 TypeScript 可选成员,因此把 options 声明为带类型参数的数据时,推荐像示例那样定义 interface Option { disabled?: boolean },从而获得完整的编译期提示。

antd 的导出体系中,这个选项类型进一步泛化为 DefaultOptionType / BaseOptionType 并随组件一并导出(参见 index.tsx 的类型导出),这也意味着基于 CascaderProps<Option> 泛型书写的 onChangeonSearch 等回调都能自动获得 disabled 字段的类型感知。

两个易混淆的禁用概念:禁用「选项」vs 禁用「整个选择器」

初学者经常把「禁用某个选项」与「禁用整个级联选择器」混为一谈,二者在 antd 中是两套完全不同的机制:

  • 逐项禁用(本文主题):写在 options 数据里,作用于下拉面板内的某一条目,由底层级联实现(@rc-component/cascader)处理,视觉上表现为该条目置灰、不可选中。
  • 整体禁用:通过组件级 disabled?: boolean 属性(默认 false)实现,作用于整个输入框,效果是点击无反应、整个控件不可用。

有意思的是,组件级 disabled 并非简单读取一个 prop。查看 Cascader 主实现,可以看到它从 config-providerDisabledContext 中读取上下文合并:

// ===================== 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 两个类名。这份快照也透露出两个信息:

  1. 一个带 children 的禁用节点并不会因为禁用而被从树中剔除,其子级结构依旧保留在数据模型中,是否继续下钻取决于底层树组件对「非叶子节点禁用」的处理约定;
  2. 面板中每个选项以 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 直接使用 colorTextDisabledcolumns.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 中关于禁用复选框、空内容禁用、多选跳过禁用子项等用例,直接对应真实用户操作。

如果你在业务中遇到「禁用不生效」或「禁用项仍被选中」等问题,可以按下列顺序自查:

  1. 确认 disabled 写在了正确的节点层级上(写在 options 的节点对象内,而不是 <Cascader> 的 props 上);
  2. 确认数据通过 options 传入且字段名确实是 disabled(未做错误的字段重命名);
  3. 确认没有在外层误用组件级 disabled/ConfigProvider componentDisabled 把整个选择器关掉;
  4. 在浏览器中检查下拉项是否带上了 ant-cascader-menu-item-disabled 类名,以此区分是「数据未生效」还是「样式被覆盖」。

小结

disabled 是 Cascader options 节点上最简单也最常用的开关之一:在 disabled-option 示例 中,它仅需一行 disabled: true 即可让任意层级的选项进入不可选中状态。但在 antd 的实现中,这背后是由类型定义、底层级联树交互、主题 token 样式与覆盖多选/搜索/空态的完整行为体系共同支撑的。理解「选项级禁用」与「控件级禁用」两条边界、掌握 .ant-cascader-menu-item-disabled 类与 colorTextDisabled token 的定制入口,再借助仓库内 demo 快照与行为测试来验证,你就能在省市区、组织树等各类多级数据选择场景中精准控制每个节点的可选性。

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