首页
/ antd Mentions 形态变体完全指南:outlined / filled / borderless / underlined 的原理与实战

antd Mentions 形态变体完全指南:outlined / filled / borderless / underlined 的原理与实战

2026-09-07 12:48:06作者:房伟宁

导读:antd 的 Mentions(提及输入框)内置四种形态变体 —— outlined(描边)、filled(填充)、borderless(无边框)、underlined(下划线),通过单个 variant 属性即可切换。本文以 variant demo 为主线,结合组件源码讲解每种变体的视觉特征、默认值与优先级规则、CSS-in-JS 实现原理,并给出在独立使用与 Form 表单场景下的落地配置,帮助你按设计规范快速产出风格统一的 @ 提及输入体验。

一、Demo 演示了什么:一行代码切换四种形态

antd 官方在 components/mentions/demo/variant.md 中展示了 Mentions 的形态变体用法,对应的可运行示例是 variant.tsx。该 Demo 的核心思想非常直观——在 Mentions 上通过 variant 属性声明形态,其余交给组件内部处理:

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

const App: React.FC = () => (
  <Flex vertical gap={12}>
    {/* 未传 variant,使用默认形态 outlined */}
    <Mentions placeholder="Outlined" />
    <Mentions placeholder="Filled" variant="filled" />
    <Mentions placeholder="Borderless" variant="borderless" />
    <Mentions placeholder="Underlined" variant="underlined" />
  </Flex>
);

export default App;

四个 Mentions 从上到下依次呈现 outlinedfilledborderlessunderlined 四种视觉效果:

变体 placeholder 提示语 典型视觉特征
outlined Outlined 白色容器 + 四边描边,聚焦带阴影光环(默认形态)
filled Filled 浅灰填充底 + 无描边感,聚焦时填充色加深
borderless Borderless 完全透明容器,无边框无背景,融入页面
underlined Underlined 仅保留底部横线,接近表单中"下划线输入"的视觉

Demo 使用 Flex vertical gap={12} 将四个控件垂直排列并保持 12px 间距,这一写法便于在文档站中横向对比不同形态的差异;在自己的页面里直接替换容器即可。

二、variant API 说明与类型约束

Mentions 组件文档 中,variant 被定义为 Mentions 核心属性之一:

属性 说明 类型 默认值 引入版本
variant Mentions 形态变体 outlined | borderless | filled | underlined outlined 5.13.0;underlined 自 5.24.0 起

几点值得注意的版本/API 细节:

  1. variant 属性自 5.13.0 起提供,underlined 变体是较晚(5.24.0)才补充的第四种形态;
  2. 该属性同时支持通过 ConfigProvider 做全局配置(表格中标注的 5.19.0 即全局生效版本),后文会展开;
  3. 底层类型并非 Mentions 私有,而是与 Input、Select、DatePicker 等输入类组件共用同一枚举。查看 components/config-provider/context.ts 可以看到类型定义:
export const Variants = ['outlined', 'borderless', 'filled', 'underlined'] as const;
export type Variant = (typeof Variants)[number];

也就是说,Variant 是一个由常量数组推导出的联合字符串类型,Mentions 与 Input、InputNumber、Select、Cascader、TreeSelect、DatePicker、TimePicker 等组件共享同一套形态体系,这也是为什么整库能保持形态语言一致。

在 Mentions 的 props 声明中(components/mentions/index.tsx),variant 是可选的 Variant 类型,JSDoc 标注了 @since 5.13.0@default "outlined",可供 IDE 智能提示直接展示默认值。

三、四种变体的底层实现:从 useVariant 到样式生成

Mentions 并未为每种形态单独写一套交互逻辑,而是通过两层机制协作:变体合并 Hook 决定最终生效的形态,CSS-in-JS 样式工厂为每种形态产出样式。理解这两层,就能解释 Demo 中所有看似"魔法"的行为。

3.1 形态优先级:useVariant 的合并规则

Mentions 内部调用 components/form/hooks/useVariants.ts 中的 useVariant 来解析最终形态,resolve 顺序如下:

// form variant > component global variant > fallback component global variant > global variant
mergedVariant = ctxVariant ?? configComponentVariant ?? configVariant ?? 'outlined';

其中:

  • ctxVariant:来自 VariantContext,通常由 Form 的 variant 属性注入;
  • configComponentVariant:ConfigProvider 中 mentions 专属的全局 variant
  • configVariant:ConfigProvider 顶层 variant(作用于所有输入类组件);
  • 兜底默认值 'outlined'

同时它还兼容了历史遗留的 bordered 属性:当 legacyBordered === false 时强制合并为 borderless,保证老代码升级不破坏视觉(useVariants.ts)。

从源码结构看,useVariant 返回的第二个布尔值 enableVariantCls 用于控制是否在 DOM 上挂载 ${prefixCls}-${variant} 形态类名,第三个布尔值用于标记是否有任何层级显式配置过形态。

3.2 形态类名如何落到 DOM 上

components/mentions/index.tsx 中,Mentions 把解析出的形态以语义化 class 的形式传给底层 @rc-component/mentions:

variant: clsx(
  {
    [`${prefixCls}-${variant}`]: enableVariantCls,
  },
  getStatusClassNames(prefixCls, mergedStatus),
),

可见形态类名(如 ant-mentions-filled)与表单状态类名(error/warning 等)是并列挂载的,因此形态与校验状态可以自由组合,这也是后面要介绍的 status demo 能同时生效的前提。

3.3 四种变体的样式来源:input/style/variants

Mentions 自己没有重复实现四种形态的视觉,而是复用输入组件家族的样式工厂。在 components/mentions/style/index.ts 中一次性引入:

genOutlinedStyle(token),
genFilledStyle(token),
genBorderlessStyle(token),
genUnderlinedStyle(token),

这四个函数定义在 components/input/style/variants.ts,各自的关键视觉效果可归纳如下(基于 genBaseOutlinedStyle 等实现):

  • outlinedbackground: colorBgContainer(白底)+ 1px 实线边框;hover 时边框变深;:focus-within 时边框高亮并追加 activeShadow(聚焦光环)。还通过 genOutlinedStatusStyle 为 error/warning 状态注册专属的边框色与阴影;
  • filled:使用填充背景色,hover/focus 时填充色变化,配合状态色做整体着色;
  • borderless:不渲染边框与背景,视觉上融入容器(可参考 genBorderlessStyle);
  • underlined:仅保留底部边框,模拟下划线式输入(可参考 genUnderlinedStyle)。

同时 Mentions 的 textarea 自身被处理为 background: transparentborder: nonestyle/index.ts),也就是说真正的"外壳"(背景、边框)由外层根元素按变体渲染,内层 textarea 保持透明,两层配合才能保证四种形态下光标、占位符与内边距表现一致。

四、全局与 Form 场景:让形态由上下文统一接管

单组件传 variant 最简单,但真实业务里通常要保证"整页/整表单形态一致"。antd 提供两套上下文方案:

4.1 ConfigProvider 全局统一

通过 ConfigProvidervariant 可为全局所有输入类组件(含 Mentions)设定统一形态;更细粒度地,可用 mentions.variant 只调整 Mentions:

import { ConfigProvider, Mentions } from 'antd';

// 整库输入类组件统一为 filled
<ConfigProvider variant="filled">
  <Mentions placeholder="全局 filled" />
</ConfigProvider>;

// 只影响 Mentions 家族
<ConfigProvider
  componentConfig={{
    mentions: { variant: 'underlined' },
  }}
>
  <Mentions placeholder="仅 Mentions 使用 underlined" />
</ConfigProvider>;

Mentions 源码通过 useComponentConfig('mentions') 读取这类组件级配置(components/mentions/index.tsx),再结合上文 useVariant 的优先级链完成合并。注意 variant 全局能力在 ConfigProvider 中自 5.19.0 起可用(见 index.en-US.md API 表)。

4.2 Form 表单统一

把 Mentions 放进 Form 时,无需逐个设置即可继承表单级形态:

import { Form, Mentions } from 'antd';

<Form variant="borderless">
  <Form.Item name="members" label="成员" rules={[{ required: true }]}>
    <Mentions placeholder="继承 Form 的 borderless" />
  </Form.Item>
</Form>;

这正是 useVariantctxVariant(VariantContext)的作用:Form 把自身 variant 下发到所有输入组件,组件的 variant 显式值会覆盖上下文值——因此"表单统一 + 个别控件特例"可以直接通过给单个 Mentions 传 variant 实现。

4.3 与状态、禁用、尺寸的组合

四种变体均可与状态类能力正交组合,常见写法如下:

<Mentions variant="filled" status="error" placeholder="校验失败提示" />
<Mentions variant="outlined" disabled placeholder="禁用态" />
<Mentions variant="underlined" size="large" placeholder="大尺寸下划线" />

样式层面,error/warning 状态色由 getStatusClassNames 与 variants 工厂中的 genOutlinedStatusStyle 等共同提供;禁用态则统一走 genDisabledStylevariants.ts),其会固定文本/背景/边框色并去除阴影,保证四种形态下禁用视觉一致。同仓库的 status demosize demo 可作对照参考。

五、设计与实现经验小结

围绕 Mentions 的 variant,可以把这套机制沉淀为几条可复用经验:

  1. 形态是"属性"而非"组件":四种变体共享同一套交互与无障碍逻辑,只替换视觉外壳,因此切换成本为零,也不存在多套组件 API 分叉问题;
  2. 优先级牢记一句话:控件自身 variant > Form 的 variant > ConfigProvider 组件级 variant > ConfigProvider 全局 variant > 默认 outlined
  3. 旧代码兼容:历史 bordered={false} 写法仍会被映射为 borderless,升级时无需逐一改写(但建议逐步迁移到新 variant 属性);
  4. 视觉定制入口统一:想微调某形态下的颜色,优先通过主题 Token(如 colorBordercolorBgContainerhoverBgactiveShadow)调整,这些 Token 同时驱动 Input/Select/Mentions 等全部输入组件,避免单组件硬编码;
  5. Demo 与真实布局:官方 variant demo 使用 Flex vertical gap 只用于示例展示,实际使用时记得为 Mentions 设置足够的宽度(容器宽度或 style),因为四种形态对边距与高度的渲染均以容器为基准。

若需要继续探索,可对照阅读 Mentions 组件总文档表单集成 demo 以及样式入口 components/mentions/style/index.ts,以理解形态变体在真实业务表单中与校验、布局、反馈图标的完整协作方式。

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391