我有以下(简化)标记代码:
<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
?
答案 0 :(得分: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);
&#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;
为了使其更加健壮,您可以在继续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);
&#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;
答案 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是事件