冒泡的反面:防止点击DOM儿童

问题描述 投票:3回答:3

我理解冒泡和event.stopPropagation()是如何工作的,但我正在寻找一种方法来避免DOM节点的所有子节点上的点击处理程序。

<div onclick="console.log('LOG ME')">
  <div onclick="console.log('DO NOT LOG ME')">Click me</div>
</div>

我希望记录“LOG ME”,但“不要记录我”不要记录。

我发现使用pointer-events: none的CSS方式,效果很好,但是,我的所有:hover,:焦点CSS样式在子div上消失了。

有任何想法吗?

编辑:一些上下文。我正在使用React。外部div是HOC,内部是可见组件。我希望HOC捕获子组件的所有点击,并停止点击传播到孩子。在React会做:

const HOC = ChildComponent => class extends Component {
  handleClick = event => { /* Do what with event? */ }

  render() {
    return <div onClick={this.handleClick}>
      <ChildComponent />
    </div>;
  }
}

其中ChildComponent是可点击的组件

javascript reactjs dom
3个回答
2
投票

更新(更新问题)

如果您正在使用react,那么在事件结束时使用Capture,以便在捕获阶段触发处理程序。 (见https://reactjs.org/docs/events.html#supported-events

所以像

const HOC = ChildComponent => class extends Component {
  handleClick = event => { 
     /* Do what with event? */
     event.stopPropagation();
     /*the rest of the code you want for handling the click*/
  }

  render() {
    return <div onClickCapture={this.handleClick}>
      <ChildComponent />
    </div>;
  }
}

您需要停止事件的传播,并且需要使用事件的捕获阶段,而不是气泡。

所以不使用onclick而是使用proper way to attach event handlers而对于你想成为容器的外部使用true作为第3个参数(useCapture参数)

document.querySelector('.outer').addEventListener('click', function(e){
  e.stopPropagation();
  console.log('LOG ME')
}, true);

document.querySelector('.inner').addEventListener('click', function(e){
  console.log('DO NOT LOG ME')
}, false);
<div class="outer">
  <div class="inner">Click me</div>
</div>

0
投票

您可以使用事件的捕获阶段挂钩到父项的单击并停止传播给子项。

你也应该关注modern standards for event registrationnot use inline HTML event attributes

// Normally, the following would set up event handler that bubbles up through all div elements
// but, you will see that it only fires once, for the parent element...
document.querySelector("div").addEventListener("click", function(evt){
  
    console.log(this);
    evt.stopPropagation();  // Don't allow the event
    
  }, true); // Adding the 3rd argument of true causes the event handler to be registered during the capture phase
<div class="parent">
  <div class="child">Click me</div>
</div>

0
投票

这可能适用于您的情况,也可能不适用,但是给定嵌套内联onclick的示例,您可以删除嵌套的onclick属性,并且不会调用事件处理程序

[].slice.call(document.querySelectorAll('[onclick] [onclick]')).forEach(function(el) {
    el.removeAttribute('onclick')
})
<div onclick="console.log('LOG ME')">
  <div onclick="console.log('DO NOT LOG ME')">Click me</div>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.