首页
/ Ant Design Cascader 形态变体(variant)完全指南:outlined / filled / borderless / underlined 的用法与实现原理

Ant Design Cascader 形态变体(variant)完全指南:outlined / filled / borderless / underlined 的用法与实现原理

2026-09-06 18:34:34作者:段琳惟

导读

Cascader 级联选择器是 Ant Design 中常见的表单组件,而它的"形态"(variant)决定了输入区域在外观上属于"描边盒子""填充块""无边框"还是"下划线式"风格。本文围绕 components/cascader/demo/variant.md 这个官方示例展开,从可直接运行的 Demo 代码出发,讲解四种形态的配置方法、默认值与版本差异,并下沉到源码层面解释形态的优先级合并逻辑、样式类名生成机制,以及 variant 与旧版 bordered API 的迁移关系,帮助你在真实业务中按需选择并统一管控表单控件外观。

四种形态变体是什么

根据 variant.md 的描述,Cascader 支持四种形态(variants):

形态取值 视觉特征
outlined 默认形态,带完整的四周边框与圆角,经典"盒子"外观
filled 背景填充样式,输入区域使用浅色底而非显式边框
borderless 无边框样式,强调内容本身、弱化容器边界
underlined 仅保留底部横线的下划线风格,常见于数据录入密度较高的表单

在类型定义上,这四种取值集中收口在 components/config-provider/context.ts

export const Variants = ['outlined', 'borderless', 'filled', 'underlined'] as const;
export type Variant = (typeof Variants)[number];

也就是说,Variant 是一个字面量联合类型,所有支持形态的组件(Input、Select、Cascader、DatePicker、TreeSelect 等)复用同一套取值,从类型层面保证了整个设计语言的一致性。

可直接运行的完整 Demo

variant.md 对应的实际代码位于 components/cascader/demo/variant.tsx,它是组件官网文档(index.en-US.md 中 "Variants" 一节的示例源文件,version="5.13.0" 标注了该能力引入版本)。完整代码如下:

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

const App: React.FC = () => (
  <Flex vertical gap="medium">
    <Cascader placeholder="Please select" variant="borderless" />
    <Cascader placeholder="Please select" variant="filled" />
    <Cascader placeholder="Please select" variant="outlined" />
    <Cascader placeholder="Please select" variant="underlined" />
  </Flex>
);

export default App;

要点拆解:

  • 用法极其简单:给 <Cascader /> 传入 variant 属性即可,无需其他配置。
  • 该示例刻意把四种形态纵向排布在同一个页面,方便直观对比各自的描边与底色差异。
  • 示例利用 Flex(flex 布局组件)搭配 gap="medium" 拉开间距,避免不同形态叠加时视觉互相干扰。
  • 示例中的 Cascader 都没有提供 options,仅展示输入框形态本身,说明 variant 是作用于输入控件外观的独立能力,与数据源、级联逻辑解耦。

实际项目中,你可以把上例中的 placeholderoptions 补全为真实的级联数据,例如省份 / 城市 / 区县,形态逻辑保持不变。

API 属性:默认值与版本差异

components/cascader/index.en-US.md 的 API 表中可以看到 variant 的权威定义:

属性 说明 类型 默认值 可用版本
variant 选择器的形态 outlined | borderless | filled | underlined outlined 5.13.0 引入;underlined5.24.0 起支持

components/cascader/index.tsx 中,属性声明与上述文档保持一致:

/**
 * @since 5.13.0
 * @default "outlined"
 */
variant?: Variant;

需要特别留意两点:

  1. 默认形态是 outlined。因此在不传 variant(也未被上层统一配置)时,Cascader 呈现的就是经典的带边框外观。
  2. underlined 是较晚补充的形态。如果你的项目锁定在 5.24.0 之前的版本,传入 underlined 不会被识别,因此在旧版本上升级使用该形态前应先确认依赖版本范围(建议升级组件库到 5.24.0+)。

旧版 bordered 属性的迁移

variant 体系引入之前,Cascader 通过布尔属性 bordered(默认 true)控制是否有边框。现在该属性已被标记为废弃(deprecated),文档明确建议改用 variant

/** @deprecated Use `variant` instead. */
bordered?: boolean;

两者存在等价的对应关系:

  • 想要无边框效果:bordered={false} 等价于 variant="borderless"
  • 想要默认带边框效果:bordered(省略或为 true)等价于默认的 outlined

为了保证兼容性,组件内部做了新旧属性互转,开发环境下还会通过 warning.deprecated 输出弃用提示,提醒开发者迁移(相关逻辑见 components/cascader/index.tsx)。结论:新代码一律使用 variant,不要再使用 bordered

从源码看形态是如何合并与生效的

形态解析入口:useVariant

Cascader 组件内部并未直接使用传入的 variant,而是统一交给表单体系下共享的 Hook useVariant 处理(调用点在 components/cascader/index.tsx):

const [variant, enableVariantCls] = useVariant('cascader', customVariant, bordered);

useVariant 实现在 components/form/hooks/useVariants.ts,其核心逻辑是形态的优先级合并组件级 variant 优先,其次是旧属性推导,最后逐级回退到上下文配置:

if (typeof variant !== 'undefined') {
  mergedVariant = variant;                                  // 1. 显式传入的 variant 属性
} else if (legacyBordered === false) {
  mergedVariant = 'borderless';                             // 2. bordered={false} 兼容推导
} else {
  // 3. 依次回退:表单 variant > 组件全局配置 > 全局 variant > 默认 outlined
  mergedVariant = ctxVariant ?? configComponentVariant ?? configVariant ?? 'outlined';
}

由此可以梳理出完整的取值优先级(高 → 低):

  1. 组件上的 variant 属性:单项覆盖,最高优先级;
  2. bordered={false}:作为历史行为被翻译为 borderless
  3. Form 提供的 VariantContext:当 Cascader 嵌套在 <Form variant="..."> 中时继承表单形态;
  4. ConfigProvider 中针对 cascader 的组件级配置
  5. ConfigProvider 顶层的全局 variant 配置
  6. 内置默认值 outlined

也就是说,你可以用 <ConfigProvider variant="underlined"> 一键把整棵组件树里的输入控件统一切到下划线风格,也可以用 <Form variant="filled"> 只影响某个表单区域,还能在单个 <Cascader variant="borderless"> 上做局部覆盖——三者在源码层面由同一个 Hook 完成合并。

形态样式如何作用到 DOM

useVariant 还会返回 enableVariantCls 标志,用于判断当前形态是否属于内置的四种合法取值(即是否存在于 Variants 常量中)。随后在渲染时,Cascader 会把形态拼进根节点类名(见 components/cascader/index.tsx):

[`${prefixCls}-${variant}`]: enableVariantCls,

例如形态为 filled 时,根元素会带上 ant-select-filled(Cascader 复用了 Select 的样式体系),从而触发对应形态的视觉规则。

样式的真正生成位于复用的 Select 样式模块中:如 components/select/style/select-input.ts 会按变体生成形态作用域的变量样式与状态覆盖,并分别对 filledborderlessunderlined 分支产出对应规则;components/select/style/select-input-multiple.tscomponents/select/style/select-input-customize.ts 则处理多选标签、自定义内容在 filled 等形态下的底色融合。因此:Cascader 的形态能力本质上复用了一套统一的 "Select-like" 输入框设计令牌,这正是它和 Select、DatePicker 等控件在形态上保持观感一致的底层原因。

全局 / 批量配置:ConfigProvider 的组件级形态

除单组件使用外,variant 也完整支持 ConfigProvider 的组件级配置。在 components/config-provider/context.ts 中可以看到,cascader 的组件配置类型同样挑选了 variant 等外观相关属性:

// 组件配置里 cascader 支持:variant、styles、classNames、expandIcon、
// loadingIcon、removeIcon、suffixIcon 等

这种设计的意义在于形态治理:当产品对某一业务模块有统一的外观诉求(例如管理后台全部采用 underlinedfilled 以降低视觉噪音)时,只需在 ConfigProvider 集中声明,而无需逐处修改每个 <Cascader /> 的写法:

<ConfigProvider
  componentConfig={{
    cascader: { variant: 'underlined' },
  }}
>
  {/* 树内所有未显式指定 variant 的 Cascader 都会使用 underlined */}
</ConfigProvider>

结合前文 useVariant 的优先级顺序可知:被 ConfigProvider 配置的形态仍可被更内层的 Form variant 或单个 Cascader 上的显式 variant 覆盖,形成"默认值 — 区域值 — 单点值"的灵活分层。

如何验证形态行为

在仓库中,该 Demo 的行为由示例快照测试保障。运行组件测试会渲染 components/cascader/demo/variant.tsx,并断言其输出与快照一致:

本地验证时,可以直接运行官方文档站点的对应页面("Cascader → Variants" 区块,标注为 5.13.0+ 可用),四种形态会以纵向排列的方式同时呈现,便于用肉眼比对填充、边框、下划线的差异,也可以打开开发者工具观察 ant-select-filled 这类形态类名是否被正确添加到 DOM 上。

小结与选型建议

围绕 variant.md 这个"一句话示例",本文将其扩展成了完整的实战指南,核心结论如下:

  • 四种形态outlined(默认)、filledborderlessunderlined,取值为统一的 Variant 联合类型;
  • 最小用法<Cascader variant="filled" />,可参考 variant.tsx 的完整示例;
  • 版本前提variant5.13.0 提供,underlined5.24.0+
  • 推荐写法:新代码使用 variant,并留意 bordered 已被废弃;
  • 批量治理:借助 <Form variant>VariantContextConfigProvidercomponentConfig.cascader.variant 实现分层控制,具体的优先级合并逻辑见 components/form/hooks/useVariants.ts
  • 实现原理:Cascader 复用 Select 的样式体系,形态会拼入根类名 ant-select-${variant},并在 select-input.ts 中按形态生成作用域样式。

选型上:默认场景直接使用 outlined;需要更柔和的输入反馈可用 filled;在紧凑的工具栏、搜索区或希望弱化组件边界的场景可考虑 borderless;追求表单密度与简约线条的桌面端数据录入场景,underlined 通常是更贴合的选择。

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