JavaScript事件和冒泡

时间:2015-04-28 19:27:01

标签: javascript javascript-events event-bubbling

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

<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/

3 个答案:

答案 0 :(得分:4)

e.target是用户点击的元素,它显示undefined,因为<span>没有data-value属性。您可以上到树中找到包含data-value的最近的祖先。

&#13;
&#13;
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);
&#13;
#container > div {
  background: red;
}
#container > div > span {
  background: blue;
  color: white;
}
&#13;
<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>
&#13;
&#13;
&#13;

为了使其更加健壮,您可以在继续node循环之前检查undefined是否为while,如果是,则退出:

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

&#13;
&#13;
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);
&#13;
#container > div {
  background: red;
}
#container > div > span {
  background: blue;
  color: white;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

当您要求的解决方案不涉及更改事件监听器时......

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

这会让点击事件直接向下冒泡到容器。

答案 2 :(得分:0)

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

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

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

其中e是事件