[Menu][Semantic] Submenu container/title/content naming & DOM-layer alignment (subItem / subItemTitle / subItemContent)
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 覆盖,故子菜单条目需单独命名。subItemContent 与 itemContent 落在同级 .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-submenuCSS、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 |
subMenu → nested(留 @deprecated 别名) |
中 | 动已发布 subMenu |
种类与层数彻底分离 |
| B(保留现状,当前实现) | subItem / subItemTitle / subItemContent |
subMenu(不变) |
已落地 | 无 | subItem 字面仍像"子级 item" |
| C | expandable 等非 submenu 词 |
subMenu(不变) |
小 | 无(改未发布) | 不如 submenu 直观 |
当前实现的是 B:结构正确、无破坏、立刻可用。**命名是否升级到 A(nested + submenu)**需团队拍板——本 issue 留此议题。
待拍板
- 是否接受 break change(动已发布
subMenu对象)? - 若是 → 方案 A;若否 → 维持当前实现的 B 现状。 3.(可选)是否给"分组容器 li"也补一个语义名,使三类条目对称(当前未做,避免额外 churn)。
Source: ant-design/ant-design