#59210·ant-design

[Menu][Semantic] Submenu container/title/content naming & DOM-layer alignment (subItem / subItemTitle / subItemContent)

Author: EmilyyyLiuCreated Sep 4, 2026Updated Sep 9, 2026
Labels🗣 Discussion

What problem does this feature solve?

填补Menu组件submenu自身元素 的Semantic DOM 空白

What does the proposed API look like?

classNames?: {
  // 新增:子菜单条目自身(一级)
  subItem?: string;           // 子菜单 <li> 容器
  subItemTitle?: string;      // 子菜单标题栏 div
  subItemContent?: string;   // 子菜单标题内容 span

  // 嵌套层对象(其中 subItem / subItemTitle / subItemContent 为新增)
  subMenu?: {
    subItem?: string;          // 新增
    subItemTitle?: string;     // 新增
    subItemContent?: string;   // 新增
  };
};
// styles 结构与 classNames 一一对应

关联 PR:#59189

背景

Menu 的 classNames / styles 语义化 API 在 6.5.x 起已发布:root / item / itemIcon / itemContent / itemTitle / list(一级),及嵌套层对象 subMenu: { item, itemIcon, itemContent, itemTitle, list }

为支持定制"可展开子菜单条目",预览新增了子菜单相关 slot,命名沿用 subItem / subItemTitle / subItemContent(以及嵌套层 subMenu.*)。其中 subItemContent 落在子菜单标题的内容 span,与叶子项 itemContent 同层。本 issue 主要留档这些命名是否需要调整

新增 slot 在 classNames 中的位置

classNames?: {
  // 已发布(6.5.x)
  root?: string;
  item?: string;
  itemIcon?: string;
  itemContent?: string;
  itemTitle?: string;
  list?: string;

  // 新增:子菜单条目自身(一级)
  subItem?: string;           // 子菜单 <li> 容器
  subItemTitle?: string;      // 子菜单标题栏 div
  subItemContent?: string;   // 子菜单标题内容 span

  // 嵌套层对象(其中 subItem / subItemTitle / subItemContent 为新增)
  subMenu?: {
    item?: string;
    itemIcon?: string;
    itemContent?: string;
    itemTitle?: string;
    list?: string;
    subItem?: string;          // 新增
    subItemTitle?: string;     // 新增
    subItemContent?: string;   // 新增
  };
};
// styles 结构与 classNames 一一对应

item 不能直接用于子菜单条目本身

叶子项(item / itemContent)与子菜单(subItem / subItemTitle / subItemContent)虽为同级条目,但 DOM 结构不同(子菜单多一层"标题栏 div 含图标与箭头"),无法用一个通用 item 覆盖,故子菜单条目需单独命名。subItemContentitemContent 落在同级 .title-content span 上,保留这种同层对应。

同一 <ul> 下三类同级条目的 DOM 对比(语义名标在元素右侧):

┌─ 叶子项 ──────────────────────────────────────
<li class="ant-menu-item">                    ← item
  └ <span class="ant-menu-title-content">      ← itemContent
└──────────────────────────────────────────────

┌─ 子菜单(可展开,比叶子多一层) ──────────────
<li class="ant-menu-submenu">                  ← subItem
  ├ <div class="ant-menu-submenu-title">       ← subItemTitle
  │   ├ <icon>                                  (itemIcon)
  │   ├ <span class="ant-menu-title-content"> ← subItemContent
  │   └ <i class="ant-menu-submenu-arrow">     (展开箭头)
  └ <ul> 嵌套
└──────────────────────────────────────────────

┌─ 分组 ────────────────────────────────────────
<li class="ant-menu-item-group">              (容器 li 当前无语义名)
  ├ <div class="ant-menu-item-group-title">   ← itemTitle
  └ <ul class="ant-menu-item-group-list">     ← list
└──────────────────────────────────────────────

仍待讨论:命名(为何预计 break change)

上述结构已自洽可用,但名字本身仍需评审,这是本 issue 主要留档点。命名矛盾的根因:

  • antd 全栈语境里"子菜单条目"最自然的词是 submenu(SubMenu 组件、.ant-menu-submenu CSS、subMenuCloseDelay / subMenuOpenDelay)。
  • 但 antd 已把 subMenu 用来命名**"嵌套层样式对象"**(firstLevel ? 一级扁平 : subMenu.*),其实际语义是"非一级 / 嵌套层",并非"一个子菜单条目"。
  • 为避开与 subMenu 撞名(只差大小写),才造了 subItem / subItemTitle / subItemContent 指代"子菜单条目";而 subItem 字面像"子级 item",与"它和 item 是同级条目"相矛盾(豆酱:"item 很直观,但和 subMenu 放一起就很蛋疼")。

submenu(条目种类)与 subMenu(层数对象)不可共存。要彻底语义化,必须让其中一个改名,而改 subMenu 会动到已发布对象 → 预计 break change。

同仓 25+ 组件 Semantic DOM 调研:item 是"条目自身"通用词,全栈一致(Dropdown / Pagination / Breadcrumb / Tabs / Tree / Segmented…),除 Menu 外无组件用 subItem / subMenu 前缀。无现成可借名先例,需 Menu 内部自洽,且不建议改 item 本身。

候选方案

方案 子菜单条目命名 嵌套层对象 改动面 破坏 语义化
A(若接受 break) submenu / submenuTitle / submenuContent subMenunested(留 @deprecated 别名) 动已发布 subMenu 种类与层数彻底分离
B(保留现状,当前实现) subItem / subItemTitle / subItemContent subMenu(不变) 已落地 subItem 字面仍像"子级 item"
C expandable 等非 submenu 词 subMenu(不变) 无(改未发布) 不如 submenu 直观

当前实现的是 B:结构正确、无破坏、立刻可用。**命名是否升级到 A(nested + submenu)**需团队拍板——本 issue 留此议题。

待拍板

  1. 是否接受 break change(动已发布 subMenu 对象)?
  2. 若是 → 方案 A;若否 → 维持当前实现的 B 现状。 3.(可选)是否给"分组容器 li"也补一个语义名,使三类条目对称(当前未做,避免额外 churn)。