Antd组件事件循环问题
事件循环知识点的实际运用
在 Ant Design 的 Dropdown/Menu 里,
直接在菜单项的 onClick 回调里同步执行 history.push 会与 Dropdown 自身的事件流产生冲突——它内部会在同一个事件循环里去处理菜单的关闭、事件的冒泡/拦截等逻辑
如果在这当下就跳路由,Dropdown 的关闭动作可能还没来得及完成,就被页面切换打断了,导致跳转不生效或者出现一些奇怪的副作用。
所以可以添加setTimeout,让路由跳转逻辑进入下一个事件循环中,这样就能保证菜单先正常收起、事件先正常冒泡,再去切换路由,跳转就一定生效了。
// 没有setTimeout的执行顺序:
onClick() → history.push() → 页面跳转 → Antd清理逻辑被中断
// 使用setTimeout(fn, 0)的执行顺序:
onClick() → Antd完成内部处理 → 下一个事件循环 → history.push()
同理,如果是其他事件,也可以参考这种方法
项目中实际使用的场景,搜索以下代码
const tranlateItem = {
label: (
<div className="cusButton">
<IconFont type="icon-Refresh" style={{ fontSize: 24 }} />
{f('多语言')}
</div>
),
key: 'translate',
onClick: async () => {
const currentLibrary = menuMap[`+${libraryId}`];
const libraryName = currentLibrary?.name || '';
const searchParams = new URLSearchParams({
from: settingType,
libraryType: libraryType,
libraryName: libraryName,
ownerType: ownerType,
libraryId: libraryId,
...(ownerId && { ownerId: ownerId.toString() }),
...(params.wsid && { wsid: params.wsid })
});
//需要添加setTimeout,让antd组件逻辑先触发,再触发路由逻辑
setTimeout(() => {
history.push(`/defenseWeaver/translation/config?${searchParams.toString()}`);
}, 0);
},
};