Ant Design的Menu菜单怎么设置选中项后不自动展开子菜单?

UI士懿 阅读 115

我在用Ant Design的侧边栏菜单时遇到个奇怪的问题。设置了mode为inline,点击父菜单项展开子菜单后,如果直接点击父菜单的选中项,整个子菜单会突然收起来,这让我很困扰。

我尝试过设置defaultOpenKeys和selectedKeys,但发现只要再次点击已选中的父菜单项,子菜单就会自动折叠。有没有办法让选中项保持展开状态呢?


<template>
  <a-menu mode="inline" :selected-keys="[currentKey]" :default-open-keys="['sub1']">
    <a-menu-item key="home">
      首页
    </a-menu-item>
    <a-sub-menu key="sub1">
      <template #title>内容管理</template>
      <a-menu-item key="article">文章列表</a-menu-item>
      <a-menu-item key="category">分类管理</a-menu-item>
    </a-sub-menu>
  </a-menu>
</template>

现在的情况是,当点击”内容管理”展开子菜单后,如果再次点击”内容管理”这个父菜单项,子菜单就会收起来。但用户可能只是想保持当前选中状态,而不是折叠菜单…

我来解答 赞 10 收藏
二维码
手机扫码查看
2 条解答
梓萱🍀
这问题我见过好几次,其实是 Ant Design Vue 的 Menu 组件默认行为导致的——它把「点击父菜单项」当成了「展开/收起」的触发动作,哪怕你已经设置了 selected-keys

解决办法有俩:

第一个是直接用 open-keys(不是 default-open-keys)配合 @open-change 手动控制展开状态,这样你就能在点击父菜单时判断:如果是已选中项,就别让它收起来。

比如你可以在 data 里定义 openKeys: ['sub1'],然后在 a-menu 上绑定 :open-keys="openKeys",再加个 @open-change="handleOpenChange"

methods: {
handleOpenChange(keys) {
// 如果是点击了父菜单项(比如 sub1),并且它已经在 openKeys 里
// 那就保持原样,别让它收起来
const activeSub = keys.find(k => k === 'sub1');
if (activeSub && this.openKeys.includes('sub1')) {
return; // 直接 return,不更新 openKeys
}
this.openKeys = keys;
}
}


然后模板里改成:

<a-menu 
mode="inline"
:selected-keys="[currentKey]"
:open-keys="openKeys"
@open-change="handleOpenChange"
>
...
</a-menu>


这样用户反复点「内容管理」,子菜单就不会收了。

第二个更偷懒的方案(适合懒人):直接在父菜单项上加个 @click.stop 阻断点击冒泡,这样点击它就不会触发展开收起逻辑了:

<a-sub-menu key="sub1">
<template #title>
<span @click.stop>内容管理</span>
</template>
...
</a-sub-menu>


不过这个方案要小心——如果后续你还想在「点击父菜单标题」时做别的事(比如跳转到某个默认页),那可能不太合适。

我一般用第一种,可控性高点。主题里加几行逻辑就行,别被它默认行为带跑偏了。
点赞 3
2026-02-26 20:05
Newb.春凤
这个问题的关键在于 Ant Design 的 Menu 组件在 inline 模式下,点击父菜单项时会默认触发折叠逻辑。要解决这个问题,可以通过控制 openKeys 来手动管理子菜单的展开状态,而不是依赖组件的默认行为。

性能上,我们尽量避免频繁的状态更新,所以可以用一个变量来记录当前展开的子菜单,只在必要时更新。

具体做法是去掉 defaultOpenKeys,改用受控属性 openKeys,并在点击事件中判断是否需要保持展开状态。下面是修改后的代码:

<template>
<a-menu
mode="inline"
:selected-keys="[currentKey]"
:open-keys="openKeys"
@open-change="handleOpenChange">
<a-menu-item key="home">
首页
</a-menu-item>
<a-sub-menu key="sub1">
<template #title>内容管理</template>
<a-menu-item key="article">文章列表</a-menu-item>
<a-menu-item key="category">分类管理</a-menu-item>
</a-sub-menu>
</a-menu>
</template>

<script>
export default {
data() {
return {
currentKey: 'home',
openKeys: ['sub1'], // 初始展开的子菜单
};
},
methods: {
handleOpenChange(keys) {
// 如果点击的是已展开的父菜单项,则保持展开状态
this.openKeys = keys.length ? keys : this.openKeys;
},
},
};
</script>


这里的核心是 @open-change 事件和 openKeys 属性的配合。handleOpenChange 方法会在用户操作菜单时触发,如果返回的 keys 是空数组(表示要折叠),我们就保留原来的 openKeys,从而避免子菜单被意外收起。

这样处理后,用户点击父菜单项时,子菜单不会自动折叠,性能上也避免了不必要的 DOM 操作。如果还有其他需求,比如动态加载子菜单,也可以在这个基础上扩展。
点赞 7
2026-02-16 14:01