You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React堆叠组件onClick事件触发冲突的解决方法咨询

问题:点击上层按钮时同时触发父组件的点击事件

我有两个通过绝对定位堆叠的React箭头函数组件(基于Material UI框架),需求是鼠标悬浮在Paper组件上时显示右上角的Button,但点击这个Button时,Paper的expandCard函数和Button的buttonAction函数会同时触发,需要解决这个问题。

简化后的代码如下:

const Card = ({...}) => {

    const styles = {
        optionsButton: {
            minWidth:0,
            minHeight: 0,
            padding: "2px",
            position: "absolute",
            color: "#808080",
            zIndex: 1,
            right: 5,
            top: 5,
            '&:hover':{
                backgroundColor: 'rgb(0, 0, 0, 0.1)'
            }
        },
    }

    const [hovering, setHovering] = useState(false)
    const [isCardExpanded, setIsCardExpanded] = useState(false)

    const expandCard = () => {
        setIsCardExpanded(true)
    }
    const closeCard = () => {
        setIsCardExpanded(false)
    }


    const mainPaperStyle = () => {
        let style = {
            padding: "10px",
            cursor: "pointer",
            position: "absolute",
            "&:hover": {
                filter: "brightness(97%)"
            }
        }

        //Extra code here modifying color of the style, no positioning modifications

        return style
    }

    const buttonAction = () => {
        console.log("Do action!")
    }

    return(
        <>
            <Paper sx={mainPaperStyle()} onClick={expandCard} onMouseEnter={() => setHovering(true)} onMouseLeave={() => setHovering(false)}>
                Lorem Ipsum

                {hovering &&
                    <Button variant="filled"
                            id="card-button"
                            sx={styles.optionsButton}
                            onClick={() => buttonAction()}>
                        <MoreVertIcon/>
                    </Button>
                }
            </Paper>
        </>
    )
}

组件效果:

  • 悬浮前:悬浮前
  • 悬浮后:悬浮后

解决方法

这个问题是事件冒泡导致的:点击子元素Button时,事件会向上传递到父元素Paper,触发父组件的onClick事件。可以通过以下两种方式解决:

方法1:在Button的点击事件中阻止冒泡

修改Button的onClick处理函数,调用event.stopPropagation()阻止事件向上传递:

<Button variant="filled"
        id="card-button"
        sx={styles.optionsButton}
        onClick={(e) => {
            e.stopPropagation(); // 阻止事件冒泡到父组件
            buttonAction();
        }}>
    <MoreVertIcon/>
</Button>

方法2:在Paper的点击事件中判断触发源

如果不想修改子组件的事件逻辑,可以在父组件Paper的onClick中判断点击目标是否为按钮元素,若是则不执行expandCard:

<Paper sx={mainPaperStyle()} 
       onClick={(e) => {
           // 检查点击目标是否是按钮或按钮的子元素
           if (!e.target.closest('#card-button')) {
               expandCard();
           }
       }} 
       onMouseEnter={() => setHovering(true)} 
       onMouseLeave={() => setHovering(false)}>
    {/* ... 组件内容 ... */}
</Paper>

内容的提问来源于stack exchange,提问作者Juan Cruz Carrau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:01:01