JS事件向下穿透,给父元素绑定事件,点击到子元素时返回的target信息为子元素(想要父元素的信息)

本文介绍了一种解决JS事件穿透问题的方法,通过使用currentTarget属性,可以准确地获取到绑定事件的元素信息,而非触发事件的元素。这在处理复杂的DOM结构时尤其有用。

    这个问题答案很简单,但困扰了我两年,先上代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JS事件穿透</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
    <div id="outDiv" data-info="out" style="border: 1px solid black;padding: 10px;">
        Out
        <div id="innerDIv"  data-info="inner" style="border: 1px solid red;padding: 5px;">
            Inner
        </div>
    </div>
</body>
<script>
    $("#outDiv").click(function (e) {
        console.log(e.target.dataset.info)
    })
</script>
</html>

效果图:

    在这段代码中,我想要实现的效果是点击Out名字的div,获取到data-info为out的信息,点击Out里面的子元素的时候,也返回我绑定事件的Out的Div的data-info的信息,但现在问题出在,当我点击Inner的div的时候,返回的是Inner这个div上的datainfo的信息,效果如图:

    我很苦恼,因为父元素里面可能会有很多子元素,一一处理起来很那,我最开始的做法是把父元素内所有的子元素都加上data-info属性,且值都和父元素一致,但这实在是一种蠢方法。网上常有的阻止事件穿透与事件冒泡,也与我的需求和场景不符。后来我打印e的时候,柳岸花明了:

    原来,e是有一个属性,叫做currentTarget,它返回的,永远是你绑定事件的元素,而不是当前触发事件的元素。

至此问题圆满解决,我想要的,就是currentTarget。

    PS:之前懒惰,在每个子元素里都添加data-info信息,现在想想实在太傻叉了。任何问题一定有解决方案,逃避是解决不了问题的,哈哈

在处理 DOM 元素嵌套结构点击父元素导致子元素事件未触发,或者相反的问题,通常与事件冒泡机制有关。以下是几种常见的解决方法: ### 1. 使用 `event.stopPropagation()` 阻止事件冒泡 当希望子元素事件独立于父元素执行,可以在子元素事件处理函数中使用 `event.stopPropagation()` 来阻止事件向上传播到父元素。 ```javascript document.querySelector('.child').addEventListener('click', function(e) { e.stopPropagation(); // 子元素的具体操作 }); ``` 通过这种方式,可以确保子元素点击事件不会触发父元素事件处理程序 [^2]。 --- ### 2. 利用 `event.target` 和 `event.currentTarget` 区分事件目标 在事件处理函数中,可以通过 `event.target`(实际被点击的元素)和 `event.currentTarget`(绑定事件的元素)来判断事件的来源,并根据需求分别处理。 ```javascript document.querySelector('.parent').addEventListener('click', function(e) { if (e.target === e.currentTarget) { // 只有点击父元素本身才执行 console.log('父元素点击'); } else { // 点击的是子元素的逻辑 console.log('子元素点击'); } }); ``` 该方式特别适用于需要区分点击是发生在父元素还是其子元素上的场景 [^1]。 --- ### 3. Vue 中使用 `.stop` 修饰符阻止事件传播 在 Vue 的模板语法中,可以直接使用 `.stop` 修饰符来阻止事件冒泡。例如,在子元素上添加 `.stop`,以防止点击子元素触发父元素事件。 ```html <div class="parent" @click="handleParentClick"> <button class="child" @click.stop="handleChildClick">点击我</button> </div> ``` 这样即使子元素位于父元素内部,也不会影响到父元素事件响应 [^2]。 --- ### 4. 判断元素层级关系进行条件执行 如果子元素覆盖了父元素,可以通过检查 `event.target` 是否属于某个特定的父级结构,决定是否执行相关逻辑。 ```javascript document.querySelector('.parent').addEventListener('click', function(e) { const isChildClicked = e.target.closest('.child'); if (isChildClicked) { console.log('子元素或其后代被点击'); } else { console.log('父元素区域被点击'); } }); ``` 此方法适用于复杂的 DOM 结构,能够更精确地控制事件行为 [^3]。 --- ### 5. 使用 CSS pointer-events 控制元素是否响应鼠标事件 在某些情况下,可以通过 CSS 设置 `pointer-events` 属性来控制子元素是否接收鼠标事件,从而间接影响父元素的行为。 ```css .child { pointer-events: auto; /* 默认值,允许响应事件 */ } .parent { pointer-events: auto; } ``` 如果想临禁用子元素的交互,可以设置为 `none`,让事件穿透父元素 [^3]。 --- ### 总结 - 如果希望子元素事件不触发父元素的逻辑,可以使用 `e.stopPropagation()` 或 Vue 的 `.stop` 修饰符。 - 如果需要区分点击对象,建议使用 `event.target` 和 `event.currentTarget` 进行判断。 - 对于复杂的 DOM 嵌套,结合 `closest()` 方法可以实现更精准的事件控制。 - 在样式层面也可以借助 `pointer-events` 实现对事件响应的精细管理。 ---
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值