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

时间:2017-12-30 16:06:00

标签: javascript reactjs dom

我理解冒泡和Couldn't match type ‘a0’ with ‘a’ because type variable ‘a’ would escape its scope This (rigid, skolem) type variable is bound by a type expected by the context: (a -> a) -> a -> a Expected type: (a -> a) -> a -> a Actual type: (a0 -> a0) -> a0 -> a0 In the first argument of ‘Church’, namely ‘fn’ 是如何工作的,但我正在寻找一种方法来避免DOM节点的所有子节点上的点击处理程序。

event.stopPropagation()

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

我找到了一种使用<div onclick="console.log('LOG ME')"> <div onclick="console.log('DO NOT LOG ME')">Click me</div> </div> 的CSS方式,效果很好,但是,所有我的:悬停,:焦点CSS样式在子div上消失了。

有什么想法吗?

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

pointer-events: none

const HOC = ChildComponent => class extends Component { handleClick = event => { /* Do what with event? */ } render() { return <div onClick={this.handleClick}> <ChildComponent /> </div>; } } 是可点击的组件

3 个答案:

答案 0 :(得分: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个参数({em> {{1}参数)

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);

答案 1 :(得分:0)

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

您还应该关注modern standards for event registrationnot use inline HTML event attributes

&#13;
&#13;
import { DialogRef } from 'ngx-modialog';

constructor(public dialogRef: DialogRef){
let context:any = dialogRef.context;
this.detail = context.data'
}
&#13;
// 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
&#13;
&#13;
&#13;

答案 2 :(得分:0)

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

&#13;
&#13;
[].slice.call(document.querySelectorAll('[onclick] [onclick]')).forEach(function(el) {
    el.removeAttribute('onclick')
})
&#13;
<div onclick="console.log('LOG ME')">
  <div onclick="console.log('DO NOT LOG ME')">Click me</div>
</div>
&#13;
&#13;
&#13;