我有以下DOM结构:
#container {
position: absolute;
width: 100px;
height: 100px;
background-color: blue;
}
#content {
position: absolute;
width: 90%;
height: 90%;
background-color: yellow;
}
#content_child {
position: absolute;
width: 30px;
height: 30px;
left: 150px;
top: 150px;
background-color: red;
}
<div id="container">
<div id="content">
<div id="content_text">Hello</div>
<div id="content_child"></div>
</div>
</div>
#content_text
和#content_child
会有各种鼠标事件。我想在#container
上检测鼠标事件。但是,如果我只是将事件附加到#container
,它们将被其子项激活,这是不可取的。我的要求如下(我使用点击事件作为例子):
#container
时,我希望其事件触发#content_text
)时,我会同时想要孩子和#container
的事件触发#content_child
),我只想 该孩子的事件触发我事先知道哪些孩子会在div之外和之内。
我可以想到两种方法,都存在很大缺陷:
#container
,并且对于div之外的每个子项,添加与附加到#container
的事件相同的事件,但使处理程序不做任何事情并使它们不传播。这有点笨拙。#container
(并且大小相同)的孩子,它会记录点击,这不会传播给它的兄弟姐妹的孩子,即#content
的孩子,因为他们是兄弟姐妹。如果我将它放在#content
之前,所有hitbox的事件都会被#content
吃掉而且它们不会触发。如果我把它放在后面,那就是相同的问题。我不能同时在同一个地方同时听同样的事件,也不能把它们传给所有的孩子。有没有办法实现一个hitbox行为没有重大的重组或花哨的Javascript(我使用榆木,所以两者都不是一个选项)?
答案 0 :(得分:2)
将处理程序附加到#container
。当您收到该事件时,如果它通过容器外的图形的子项,则忽略它。
您可以通过检查事件对象上的target
和(如果需要)parentNode
等来确定点击进入容器的路径,直到您到达容器。< / p>
这是一个例子(在这里,我硬编码检查孩子是否在父母内部以图形方式,因为你说你已经知道了;不需要进入工作通过一个简单的例子来解决这个问题):
function hook(selector, event, handler) {
var elements = document.querySelectorAll(selector);
Array.prototype.forEach.call(elements, function(el) {
el.addEventListener(event, handler, false);
});
}
// container's click handler
hook("#container", "click", function(e) {
if (passedThroughChildOutsideBox(e, this)) {
// Ignore
} else {
console.log("container click");
}
});
// child handlers
hook("#content_text, #content_child", "click", function(e) {
console.log(this.id + " click");
});
// Fake detection
function passedThroughChildOutsideBox(e, container) {
var node = e.target;
while (node && node !== container) {
if (node.id === "content_child") { // Again, just hardcoded for demo
return true;
}
node = node.parentNode;
}
return false;
}
&#13;
#container {
position: absolute;
width: 100px;
height: 100px;
background-color: blue;
}
#content {
position: absolute;
width: 90%;
height: 90%;
background-color: yellow;
}
#content_child {
position: absolute;
width: 30px;
height: 30px;
left: 150px;
top: 150px;
background-color: red;
}
&#13;
<div id="container">
<div id="content">
<div id="content_text">Hello</div>
<div id="content_child"></div>
</div>
</div>
&#13;
答案 1 :(得分:0)
使用停止传播https://developer.mozilla.org/en/docs/Web/API/Event/stopPropagation
将阻止进一步传播..
var container = document.getElementById("container");
var container_text = document.getElementById("content_text");
var container_child = document.getElementById("content_child");
container.addEventListener("click", function () {
console.log('this is the container');
});
container_text.addEventListener("click", function () {
console.log('this is the container_text');
});
container_child.addEventListener("click", function (event) {
event.stopPropagation();
console.log('this is the container_child');
});
#container {
position: absolute;
width: 100px;
height: 100px;
background-color: blue;
}
#content {
position: absolute;
width: 90%;
height: 90%;
background-color: yellow;
}
#content_child {
position: absolute;
width: 30px;
height: 30px;
left: 150px;
top: 150px;
background-color: red;
}
<div id="container">
<div id="content">
<div id="content_text">Hello</div>
<div id="content_child"></div>
</div>
</div>
答案 2 :(得分:0)
尝试e.stopPropagation()会阻止父母点击查找子事件。
#container {
position: absolute;
width: 100px;
height: 100px;
background-color: blue;
}
#content {
position: absolute;
width: 90%;
height: 90%;
background-color: yellow;
}
#content_text {
background: grey;
}
#content_child {
position: absolute;
width: 30px;
height: 30px;
left: 150px;
top: 150px;
background-color: red;
color: #fff;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="content">
<div id="content_text">Hello</div>
<div id="content_child">hi</div>
</div>
</div>
&#13;
{{1}}&#13;
https://codepen.io/anon/pen/zZbYvp
// codepen.io/anon/pen/zZbYvp