我的页面上有一些嵌套元素,它们上面有相同的处理程序,只应为事件目标调用,而不会影响DOM树中较高的元素。为了实现这种行为,我使用了stopPropagation方法,它没问题。然后我必须为嵌套div之外的body和其他元素添加一些处理程序,在任何情况下都应该调用它们。当然,stopPropagation现在不是一个选项,但我怎样才能使它工作?
以下是一个示例:
HTML:
<div id="container">
<div id="nested1" class="nested">
<div id="nested2" class="nested">
<div id="nested3" class="nested">
<div id="no-handler"></div>
</div>
</div>
</div>
</div>
的CSS:
#container {
display: block;
width: 398px;
height: 398px;
padding: 30px;
border: solid 1px #888;
}
#nested1 {
width: 336px;
height: 336px;
padding: 30px;
}
#nested2 {
width: 274px;
height: 274px;
padding: 30px;
}
#nested3 {
width: 212px;
height: 212px;
padding: 30px;
}
#no-handler {
width: 150px;
height: 150px;
padding: 30px;
border: solid 1px #888;
}
.nested {
border: solid 1px #888;
}
.nested-clicked {
background-color: red;
}
.outer-clicked {
background-color: green;
}
JS:
var container = document.getElementById("container");
var nested = document.getElementsByClassName("nested");
function outerHandler(e) {
this.classList.add("outer-clicked");
}
function nestedHandler(e) {
e.stopPropagation();
this.classList.add("nested-clicked");
}
container.addEventListener("click", outerHandler, false);
document.body.addEventListener("click", outerHandler, false);
for (var i = 0; i < nested.length; i++) {
nested[i].addEventListener("click", nestedHandler, false);
}
jsfiddle链接: http://jsfiddle.net/6kgnu7fr/
点击.nested
会为点击的元素添加红色背景颜色,并将绿色添加到外部body
和#container
UPD:
http://jsfiddle.net/6kgnu7fr/2/
点击#no-event
或.nested
内的任何其他元素也应该为此.nested
元素调用nestedHandler。
答案 0 :(得分:1)
您可以在target
中检查事件的nestedHandler
,而不是停止传播。仅当目标为class
时才更改this
,以便仅对发生事件的div
应用效果:
function nestedHandler(e) {
if (e.target === this) {
this.classList.add("nested-clicked");
}
}
修改强>
编辑之后,这就更难了。这样做的方法是使用“嵌套”类找到e.target
的第一个祖先,然后用它来代替target
进行比较:
function findAncestorWithClass(dom, targetClass){
if(!dom){
return; // (undefined)
}
if(dom.classList.contains(targetClass)){
return dom;
}
// terminal recursion
return findAncestorWithClass(dom.parentNode, targetClass);
}
这是天真的镜头。您可能希望寻找一种方法来提高效率,例如:通过避免在每个.nested
div上寻找第一个祖先。
请参阅下面的工作内容。
var container = document.getElementById("container");
var nested = document.getElementsByClassName("nested");
function outerHandler(e) {
this.classList.add("outer-clicked");
}
function findAncestorWithClass(dom, targetClass){
if(!dom){
return; // (undefined)
}
if(dom.classList.contains(targetClass)){
return dom;
}
// terminal recursion
return findAncestorWithClass(dom.parentNode, targetClass);
}
function nestedHandler(e) {
var nestedParent = findAncestorWithClass(e.target, "nested");
if (this === nestedParent) {
nestedParent.classList.add("nested-clicked");
}
}
container.addEventListener("click", outerHandler, false);
document.body.addEventListener("click", outerHandler, false);
for (var i = 0; i < nested.length; i++) {
nested[i].addEventListener("click", nestedHandler, false);
}
#container {
display: block;
width: 398px;
height: 398px;
padding: 30px;
border: solid 1px #888;
}
#nested1 {
width: 336px;
height: 336px;
padding: 30px;
}
#nested2 {
width: 274px;
height: 274px;
padding: 30px;
}
#nested3 {
width: 212px;
height: 212px;
padding: 30px;
}
#sub-nested {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
.nested {
border: solid 1px #888;
}
.nested-clicked {
background-color: red;
}
.outer-clicked {
background-color: green;
}
<div id="container">
<div id="nested1" class="nested">
<div id="nested2" class="nested">
<div id="nested3" class="nested">
<div id="sub-nested"></div>
</div>
</div>
</div>
</div>