首页
/ antd Cascader 多选模式(multiple)实战:disableCheckbox 禁用勾选与禁用态样式定制

antd Cascader 多选模式(multiple)实战:disableCheckbox 禁用勾选与禁用态样式定制

2026-09-06 18:26:47作者:苗圣禹Peter

导读

Cascader 是 Ant Design 中用于层级选择的核心组件,默认只允许单选一个末级节点;本篇文章聚焦其「多选(multiple)」使用场景。你将学会如何在 options 数据上通过 disableCheckbox 字段单独禁用某一个节点的 checkbox、如何理解父级全选时对禁用节点的处理逻辑,以及如何借助 CSS 类名定制禁用态的视觉样式。文章以仓库中的 multiple.md 官方演示为主体,并结合 源码实现测试用例 深入剖析其底层机制。

一次选择多个选项:多选模式的基础用法

Cascader 的多选能力由 multiple 属性开启。仓库中的官方演示 multiple.tsx 给出了最小可运行示例,其核心代码如下:

import React from 'react';
import type { CascaderProps } from 'antd';
import { Cascader } from 'antd';

const onChange: CascaderProps<Option, 'value', true>['onChange'] = (value) => {
  console.log(value);
};

const App: React.FC = () => (
  <Cascader
    style={{ width: '100%' }}
    options={options}
    onChange={onChange}
    multiple
    maxTagCount="responsive"
  />
);

export default App;

关键点说明:

  • multiple:布尔属性,置为 true 后下拉面板中每个选项前会出现 checkbox,已选项以标签(Tag)形式回填到输入框中。从 CascaderProps 的类型定义可以看到 multiple?: Multiple,且存在泛型 Multiple extends boolean,TS 会据此推导出 onChange 回调中 value 的结构。
  • maxTagCount="responsive":控制已选标签的最大展示数量,"responsive" 表示当标签宽度超出容器时自动折叠为 +N,适用于大量多选的场景,避免输入框被标签撑满。
  • onChange 的类型签名:多选时回调参数 value 是「二维数组」,每一项对应一条从根到叶的完整路径,例如 [['bamboo', 'little', 'fish']]。上面用 CascaderProps<Option, 'value', true>['onChange'] 精确标注了多选版本的回调类型。
  • options:级联数据源,接口定义为 { value, label, children?, disableCheckbox? },其中 children 递归声明层级,disableCheckbox 是本文的核心字段,见下一节。

提示:上述示例可直接在仓库 demo 页面中运行调试,类型导入 import { Cascader } from 'antd' 与日常业务使用方式一致。

数据层:用 disableCheckbox 字段禁用单个 checkbox

多选场景下,「禁用」是分级别的——我们通常希望在整棵级联树可用的前提下,仅让某一个特定节点无法被勾选。此时不需要设置组件级 disabled(那会整体失效),而是在该节点的数据中声明 disableCheckbox: true

multiple.tsx 的数据结构中,示例把 disableCheckbox 声明为 Option 接口的可选字段,并作用于第三层叶子节点:

interface Option {
  value: string | number;
  label: string;
  children?: Option[];
  disableCheckbox?: boolean;
}

// 摘录:位于 Bamboo → Little 路径下的叶子节点
{
  label: 'Toy Fish',
  value: 'fish',
  disableCheckbox: true, // 该节点的 checkbox 被禁用,无法勾选
}

这段数据在「字段自定义」层面说明了 disableCheckbox 的取值对象:它是作用于单个 option 节点的数据字段,而非 Cascader 组件的顶层属性。它只影响多选模式下 checkbox 的勾选状态:

  • 被标记的节点,其前方的 checkbox 呈现禁用态,用户无法通过点击它完成勾选;
  • 其它同级、父级节点不受影响,可以正常勾选与取消。

disabled 字段的区别

同目录下的 disabled-option.md 演示了另一种禁用方式——通过在 options 中指定 disabled 字段来整体禁用某个选项(该节点不可点击、不可选中,通常还伴随灰显样式)。二者适用场景不同,可对照选用:

数据字段 生效前提 禁用粒度
disabled 单选/多选均生效 整个选项(含路径点击)不可用
disableCheckbox 多选(multiple)模式下生效 仅该节点的勾选框被禁用

源码机制:multiple 是如何变成 checkbox 的

在 Ant Design 的封装层,multiple 并不会直接透传给底层组件,而是被转换成了一个 checkable 渲染结果。查看 useCheckable.tsx,逻辑非常简洁:

import * as React from 'react';

export default function useCheckable(cascaderPrefixCls: string, multiple?: boolean) {
  return React.useMemo(
    () => (multiple ? <span className={`${cascaderPrefixCls}-checkbox-inner`} /> : false),
    [cascaderPrefixCls, multiple],
  );
}

由此可以推断整个调用链路:

  1. Cascader 主体组件 中调用 useCheckable(cascaderPrefixCls, multiple),把布尔型 multiple 翻译成带 -checkbox-inner 类名的 React 元素;
  2. 该元素作为 checkable 属性传入底层 @rc-component/cascader<RcCascader checkable={checkable} ... />);
  3. rc-cascadercheckable 存在时即为每个节点渲染 checkbox,实现多选与父子联动勾选逻辑。

也就是说:Cascader 的「多选」在底层实现上就是「可勾选(checkable)」,而 disableCheckbox 正是 rc-cascader 在渲染 checkbox 时识别的禁用信号,最终表现为 checkbox 呈现禁用态且不参与勾选。

多选回填策略:SHOW_CHILD 与 SHOW_PARENT

多选模式下,父子节点同时被勾选后存在「回填哪些路径」的问题。仓库在 index.tsx 中直接从底层组件导出两个常量:

const { SHOW_CHILD, SHOW_PARENT } = RcCascader;

并挂载为 Cascader.SHOW_PARENTCascader.SHOW_CHILDindex.tsx),供业务方通过 showCheckedStrategy 指定回填粒度。可参考配套演示 showCheckedStrategy.tsx

const { SHOW_CHILD } = Cascader;

<Cascader
  options={options}
  onChange={onChange}
  multiple
  maxTagCount="responsive"
  showCheckedStrategy={SHOW_CHILD}
  defaultValue={[
    ['bamboo', 'little', 'fish'],
    ['bamboo', 'little', 'cards'],
    ['bamboo', 'little', 'bird'],
  ]}
/>
  • SHOW_CHILD:只回填叶子节点(子项)路径;
  • SHOW_PARENT:当某父级下所有子项都被勾选时,仅回填父级路径。

该属性与 disableCheckbox 都属于多选行为配置,在实战中常组合使用,用来控制最终提交给后端的 value 形态。

禁用态的样式定制:通过类名修改

官方演示 multiple.md 特别指出:disableCheckbox 节点的禁用样式可以通过类名进行修改。要精准定制,就需要知道实际渲染出的 DOM 类名。从 测试用例 可以确认关键类名:

expect(container.querySelectorAll('.ant-cascader-checkbox-disabled')).toHaveLength(1);
expect(container.querySelectorAll('.ant-cascader-checkbox')).toHaveLength(4);
expect(container.querySelectorAll('.ant-cascader-checkbox-checked')).toHaveLength(3);

即在多选下拉面板中:

  • 每个节点前的勾选框渲染为 .ant-cascader-checkbox
  • 处于禁用态的勾选框额外叠加 .ant-cascader-checkbox-disabled(即 disableCheckbox 生效时节点出现的禁用类);
  • 被勾选的节点呈现 .ant-cascader-checkbox-checked

通过 CSS 覆盖禁用样式

获得类名后,可用 CSS 自行覆盖禁用态视觉效果,例如让禁用 checkbox 呈现自定义颜色而不只是默认灰显:

/* 修改禁用 checkbox 的外观:去掉默认全灰,改为描边 + 斜杠提示 */
.ant-cascader-checkbox-disabled .ant-cascader-checkbox-inner {
  border-color: #ff7875;
  background: #fff1f0;
}

.ant-cascader-checkbox-disabled.ant-cascader-checkbox-checked
  .ant-cascader-checkbox-inner {
  background-color: #ff7875;
}

注意:类名中的 cascader 前缀对应默认 prefixCls(即 ant-),若通过 ConfigProvider 或组件 prefixCls 修改了前缀,请同步替换选择器前缀。

样式作用域如何限定

若担心全局覆写影响其它页面,推荐将覆盖样式绑定在组件级 className 上。示例中 Cascader 接收 style={{ width: '100%' }},同样地你可以传入 className/rootClassName 限定输入框根节点;而下拉面板的类名可通过 classNames.popup.root(v5 语义化 API)或兼容的 popupClassName 指定。将上述选择器写成 my-cascader .ant-cascader-checkbox-disabled ...,即可把样式限制在当前组件范围内。

行为验证:父级全选会「跳过」被禁用的子节点

disableCheckbox 一个容易误解的行为点是:当父节点 checkbox 被勾选(全选所有子节点)时,被禁用 checkbox 的子节点是否会被一并选中?仓库测试 index.test.tsx 明确给出了预期:

“Check all children except disableCheckbox When the parent checkbox is checked”——勾选父节点时,除 disableCheckbox 节点外的所有子节点被选中。

测试构造了如下结构并断言点击父级 checkbox 后,被勾选项数量为 3(而非 4,因为 fj 节点声明了 disableCheckbox: true):

<Cascader
  multiple
  options={[
    {
      label: '台湾',
      value: 'tw',
      children: [
        { label: '福建', value: 'fj', disableCheckbox: true },
        { label: '兰州', value: 'lz' },
        { label: '北京', value: 'bj' },
      ],
    },
  ]}
/>

同时断言面板中该节点确实带 .ant-cascader-checkbox-disabled 禁用类。因此我们可以将这一行为总结为产品层面的明确契约:

  • 禁用节点永远不被自动勾选——即使父级执行「全选」,disableCheckbox 节点也会被自动跳过;
  • 禁用节点不阻断父级操作——父节点仍可正常勾选其允许选中的子项。

这一细节对“不完全级联选择”类业务(如目录权限、区域配额)至关重要,可直接作为验收用例写入团队测试。

写在最后:多选 Cascader 的组合使用建议

综合官方演示与仓库实现,落地一个多选 Cascader 时建议按以下顺序梳理需求:

  1. 开启多选:设置 multiple,必要时配合 maxTagCount 控制已选标签展示;
  2. 定义数据模型:在 Option 类型中补充 disableCheckbox?: boolean,对个别禁勾节点置为 true;若需整体禁用选项则改用 disabled 字段;
  3. 处理回填策略:按后端需要的 value 形态设置 showCheckedStrategy={Cascader.SHOW_CHILD}SHOW_PARENT
  4. 定制禁用样式:利用 .ant-cascader-checkbox-disabled 类名(配合组件级 className 限定作用域)覆盖默认灰显效果;
  5. 验证父子联动:参照 测试用例 的行为契约,确保禁用节点在父级全选时被正确跳过。

说明:Cascader 基于 rc-cascader 实现多选与勾选联动,disableCheckbox 属于数据层(option 字段)能力;相关实现可继续阅读 Cascader 封装入口useCheckable 钩子 深入理解。

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