Skip to content

[BUG] [Dropdown] 嵌套 Dropdown 点击子菜单触发父级 onClickOutSide,导致子菜单 onClick 事件丢失 #3118

@xshuxin

Description

@xshuxin

Is there an existing issue for this?

  • I have searched the existing issues

Which Component

Dropdown

Semi Version

2.87.1

Current Behavior

问题描述

在使用嵌套 Dropdown 时,点击子 Dropdown 的菜单项会优先触发父级 Dropdown 的 onClickOutSide 事件并导致父级立即关闭(卸载)。 核心问题是:子菜单项绑定的 onClick 事件因此无法触发(丢失) 。

看起来父级 Dropdown 将点击子菜单(Portal DOM)视为“点击外部”,在子元素事件响应之前就关闭了整个组件树。

Expected Behavior

点击子菜单时执行 onClick

Steps To Reproduce

复现步骤

  1. 创建父级 Dropdown ( trigger="custom" ) 并绑定 onClickOutSide 以关闭菜单。
  2. 嵌套一个子 Dropdown,并在子菜单项上绑定 onClick (例如 console.log )。
  3. 打开菜单并点击子菜单项。
  4. 观察结果 :父级 onClickOutSide 被触发,菜单关闭,但子菜单项的 onClick 未执行 。

最小复现 Demo

import React, { useState } from 'react';
import { Dropdown, Button } from '@douyinfe/semi-ui';

export default function Demo() {
    const [visible, setVisible] = useState(true);

    return (
        <div style={{ padding: 50 }}>
            <Dropdown
                trigger="custom"
                visible={visible}
                onClickOutSide={() => {
                    console.log('1. 父级 onClickOutSide 触发,准备关闭');
                    setVisible(false); 
                }}
                content={
                    <Dropdown.Menu>
                        <Dropdown 
                            position="rightTop" 
                            render={
                                <Dropdown.Menu>
                                    <Dropdown.Item onClick={() => console.log('2. 子菜单 onClick 触发(预期应能看到此日志)')}>
                                        点击我(事件会丢失)
                                    </Dropdown.Item>
                                </Dropdown.Menu>
                            }
                        >
                            <Dropdown.Item>Hover 展开子菜单</Dropdown.Item>
                        </Dropdown>
                    </Dropdown.Menu>
                }
            >
                <Button onClick={() => setVisible(true)}>打开 Dropdown</Button>
            </Dropdown>
        </div>
    );
}

ReproducibleCode

import React, { useState } from 'react';
import { Dropdown, Button } from '@douyinfe/semi-ui';

export default function Demo() {
    const [visible, setVisible] = useState(true);

    return (
        <div style={{ padding: 50 }}>
            <Dropdown
                trigger="custom"
                visible={visible}
                onClickOutSide={() => {
                    console.log('1. 父级 onClickOutSide 触发,准备关闭');
                    setVisible(false); 
                }}
                content={
                    <Dropdown.Menu>
                        <Dropdown 
                            position="rightTop" 
                            render={
                                <Dropdown.Menu>
                                    <Dropdown.Item onClick={() => console.log('2. 子菜单 onClick 触发(预期应能看到此日志)')}>
                                        点击我(事件会丢失)
                                    </Dropdown.Item>
                                </Dropdown.Menu>
                            }
                        >
                            <Dropdown.Item>Hover 展开子菜单</Dropdown.Item>
                        </Dropdown>
                    </Dropdown.Menu>
                }
            >
                <Button onClick={() => setVisible(true)}>打开 Dropdown</Button>
            </Dropdown>
        </div>
    );
}

Environment

- OS:
- browser:

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions