【问题标题】:How to get click on parent tag if I click on any child, grandchild (and deeper) in document.body.addEventListener如果我点击 document.body.addEventListener 中的任何孩子、孙子(和更深的),如何点击父标签
【发布时间】:2019-12-20 11:27:19
【问题描述】:

我需要在我的 script.js 中应用事件委托方法。所以,我需要捕捉 body 标签上的所有“点击”事件。它不能改变。我用:

document.body.addEventListener('click', function(event) {
  ... // here I catch clicks on different elements
}, true);

我有一个父块和未知数量的内部嵌套块、子/孙/孙...等。

我想在父区域、子、孙子区域中的任意位置单击,然后我想在 event.target.classList 数组中捕获具有“父”类名称的事件。

请查看示例代码https://codepen.io/appalse/pen/xxbqWLr

document.body.addEventListener('click', function(event) {
  alert(event.target.classList);
  if (event.target.classList.contains('parent')) {
    /* I want to catch certain target with 'parent' class name */
    event.target.classList.toggle('yellow-background');
  }

}, true);
div {
  border: 1px solid black;
  margin: 10px;
  padding: 10px;
}

div.parent {
  border-width: 3px;
}

.container {
  width: 300px;
  background-color: lightgrey;
}

.parent {
  background-color: lightblue;
  cursor: pointer;
}

.child {
  background-color: lightgreen;
}

.grandchild {
  background-color: cyan;
}

.yellow-background {
  background-color: yellow;
}
<div class="container"> Container
  <div class="parent"> Parent - it catches click. OK
    <div class="child">Child - doesn't catch click.
      <div class="grandchild">Grandchild - doesn't catch click</div>
      <div class="grandchild">Grandchild - doesn't</div>
    </div>
  </div>
</div>

我已阅读有关冒泡和捕获事件的信息。我在 addEventListener 中使用了“useCapture = true”值,以便在捕获阶段捕获事件。但它以另一种方式工作。我认为 addEventListener 方法是为点击区域下的每个标签调用的,但我看到 addEventListener 方法只为最后一个子事件调用。

我不能使用 event.target.parentNode 因为我不知道这个目标孩子有多深。但是,我可以递归调用 parentNode,直到获得必要的父节点。但是这个解决方案对我来说看起来很奇怪,就像一个黑客。我错了吗?这种递归方法是否普遍且良好?

这个问题似乎很基础,但在“捕获和冒泡”、“事件委托”等文章中,我只看到了最简单的示例,没有未知数量的嵌套元素。或者他们提出了在父标签上使用 addEventListener 方法的解决方案,我不能使用(因为我使用 document.body.addEventListener)。

请帮助我找到解决方案并更好地了解此问题。任何链接或谷歌关键字将不胜感激。

【问题讨论】:

    标签: javascript event-handling click dom-events addeventlistener


    【解决方案1】:

    使用event.target.closest('.parent') 查看被点击的元素是否有一个.parent 的祖先。如果是,就改变父类,否则什么都不做:

    document.body.addEventListener('click', function(event) {
      const parent = event.target.closest('.parent');
      if (parent) {
        parent.classList.toggle('yellow-background');
      }
    }, true);
    div {
      border: 1px solid black;
      margin: 10px;
      padding: 10px;
    }
    
    div.parent {
      border-width: 3px;
    }
    
    .container {
      width: 300px;
      background-color: lightgrey;
    }
    
    .parent {
      background-color: lightblue;
      cursor: pointer;
    }
    
    .child {
      background-color: lightgreen;
    }
    
    .grandchild {
      background-color: cyan;
    }
    
    .yellow-background {
      background-color: yellow;
    }
    <h1>How to catch an event on Parent element (event.target.classList should contain 'parent') if I click on any of Grandchild / Child / Parent?</h1>
    <div class="container"> Container
      <div class="parent"> Parent - it catches click. OK
        <div class="child">Child - doesn't catch click.
          <div class="grandchild">Grandchild - doesn't catch click</div>
          <div class="grandchild">Grandchild</div>
        </div>
        <div class="child">
          <div class="grandchild">Grandchild</div>
          <div class="grandchild">Grandchild</div>
        </div>
      </div>
    </div>
    <div class="container">
      <div class="parent"> Parent - should catch click
        <div class="child">
          <div class="grandchild">Grandchild</div>
          <div class="grandchild">Grandchild</div>
        </div>
        <div class="child">
          <div class="grandchild">Grandchild</div>
          <div class="grandchild">Grandchild</div>
        </div>
      </div>
    </div>

    冒泡与捕获在这里并没有太大区别 - 至少在这种情况下,您也可以在冒泡阶段附加侦听器,它也可以正常工作。

    我认为 addEventListener 方法是为点击区域下的每个标签调用的,但我看到 addEventListener 方法只为最后一个子事件调用。

    被点击元素的每个祖先元素都会运行一个点击事件监听器,如果它有一个附加到元素上 - 但是在这里,你只有一个点击监听器,附加到document.body,所以只有一个回调运行当有点击时。

    【讨论】:

    • 非常感谢!它有效,这正是我所需要的。
    【解决方案2】:

    只需将监听器添加到document.body,让事件冒泡解决您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-02
      • 2021-08-06
      相关资源
      最近更新 更多