JavaScript事件和冒泡

问题描述 投票:5回答:3

我有以下(简化的)标记代码:

<div id="container">
    <div data-value="1">
        <span>Click me 1</span>
    </div>
    <div data-value="2">
        <span>Click me 2</span>
    </div>
</div>
<div id="messages"></div>

我想通过仅在#container上附加事件监听器来获得冒泡的优势,并获得被点击的孩子的data-value

document.getElementById('container').addEventListener('click', function(e){
    document.getElementById('messages').innerHTML = 'you clicked ' + e.target.dataset.value;
}, false);

如果单击的区域是div区域(小提琴中为红色),则一切正常。当单击来自div子级(例如,单击蓝色范围)且具有数据值而不更改事件侦听器时,如何获得data-value

这里是小提琴:http://jsfiddle.net/hgLagy31/1/

javascript dom-events event-bubbling
3个回答
4
投票
e.target是用户单击的元素,由于undefined不具有<span>属性,因此显示data-value。您可以上树,找到包含data-value的最近祖先。

document.getElementById('container').addEventListener('click', function(e) { // Find nearest ancestor with data-value defined var node = e.target; while (!node.dataset.value) { node = node.parentNode; } document.getElementById('messages').innerHTML = 'you clicked ' + node.dataset.value; }, false);
#container > div {
  background: red;
}
#container > div > span {
  background: blue;
  color: white;
}
<div id="container">
  <div data-value="1">
    <span>Click me 1</span>
  </div>
  <div data-value="2">
    <span>Click me 2</span>
  </div>
</div>
<div id="messages"></div>
为了使其更健壮,您可以在继续进入node循环之前检查undefined是否为while,如果是,则退出:

while (!node.dataset || !node.dataset.value) { node = node.parentNode; if (!node) { document.getElementById('messages').innerHTML = 'Could not find data-value'; return; } }

 

document.getElementById('container').addEventListener('click', function(e) { // Find nearest ancestor with data-value defined var node = e.target; while (!node.dataset || !node.dataset.value) { node = node.parentNode; if (!node) { document.getElementById('messages').innerHTML = 'Could not find data-value'; return; } } document.getElementById('messages').innerHTML = 'you clicked ' + node.dataset.value; }, false);
#container > div {
  background: red;
}
#container > div > span {
  background: blue;
  color: white;
}
<div id="container">
  <div data-value="1">
    <span>Click me 1</span>
  </div>
  <div data-value="2">
    <span>Click me 2</span>
  </div>
  <div>
    <span>Click me 3</span>
  </div>
</div>
<div id="messages"></div>

0
投票
您所要求的解决方案不涉及更改事件侦听器...

#container > div > span { background: blue; color: white; pointer-events: none; }

这将使click事件直接冒泡到容器。

0
投票
正如其他人提到的,获取目标元素,然后遍历.parentNode

并非所有浏览器都支持target / toElement,因此在获取目标元素时使用以下polyfill:

var target = e.toElement || e.relatedTarget || e.target || function () { throw "Failed to attach an event target!"; }

事件在哪里
© www.soinside.com 2019 - 2024. All rights reserved.