JavaScript 事件和冒泡
JavaScript events and 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
上附加事件侦听器来利用冒泡,并获得点击的 children 的 data-value
。
document.getElementById('container').addEventListener('click', function(e){
document.getElementById('messages').innerHTML = 'you clicked ' + e.target.dataset.value;
}, false);
如果单击的区域是 div
区域(fiddle 中的红色区域),则一切正常。当点击来自 div 的 children(例如点击蓝色跨度)时,我如何在不更改事件侦听器的情况下获得具有数据值的 data-value
?
这是 fiddle:http://jsfiddle.net/hgLagy31/1/
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>
为了使其更健壮,您可以在继续 while
循环之前检查 node
是否为 undefined
,如果是则退出:
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>
当您要求不涉及更改事件侦听器的解决方案时...
#container > div > span {
background: blue;
color: white;
pointer-events: none;
}
这将使点击事件直接冒泡到容器。
正如其他人提到的获取目标元素然后遍历.parentNode
并非所有浏览器都支持target/toElement,所以我在获取目标元素时使用了以下polyfill:
var target = e.toElement || e.relatedTarget || e.target || function () { throw "Failed to attach an event target!"; }
其中 e 是事件
我有以下(简化的)标记代码:
<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
上附加事件侦听器来利用冒泡,并获得点击的 children 的 data-value
。
document.getElementById('container').addEventListener('click', function(e){
document.getElementById('messages').innerHTML = 'you clicked ' + e.target.dataset.value;
}, false);
如果单击的区域是 div
区域(fiddle 中的红色区域),则一切正常。当点击来自 div 的 children(例如点击蓝色跨度)时,我如何在不更改事件侦听器的情况下获得具有数据值的 data-value
?
这是 fiddle:http://jsfiddle.net/hgLagy31/1/
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>
为了使其更健壮,您可以在继续 while
循环之前检查 node
是否为 undefined
,如果是则退出:
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>
当您要求不涉及更改事件侦听器的解决方案时...
#container > div > span {
background: blue;
color: white;
pointer-events: none;
}
这将使点击事件直接冒泡到容器。
正如其他人提到的获取目标元素然后遍历.parentNode
并非所有浏览器都支持target/toElement,所以我在获取目标元素时使用了以下polyfill:
var target = e.toElement || e.relatedTarget || e.target || function () { throw "Failed to attach an event target!"; }
其中 e 是事件