我理解冒泡和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
是可点击的组件
更新(更新问题)
如果您正在使用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>
您可以使用事件的捕获阶段挂钩到父项的单击并停止传播给子项。
你也应该关注modern standards for event registration和not 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>
这可能适用于您的情况,也可能不适用,但是给定嵌套内联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>