我的页面上有一些嵌套的元素,它们具有相同的处理程序,只应为事件目标调用它们,而不会影响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。

最佳答案

您可以在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>

关于javascript - 继续传播,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33298114/

10-12 12:25