简体   繁体   English

React - 防止父事件触发子事件

[英]React - Prevent Event Trigger on Parent From Child

I have this scenario, where when parent element is clicked, it flips to show a child element with different colours.我有这种情况,当单击父元素时,它会翻转以显示具有不同颜色的子元素。 Unfortunately, when the user clicks on one of the colours, the 'click' event on parent is also triggered.不幸的是,当用户点击其中一种颜色时,父级上的“点击”事件也会被触发。

How can I stop the event trigger on parent when the child is clicked?单击子项时如何停止父项上的事件触发器?

Possible solutions I am wondering:我想知道可能的解决方案:

  1. CSS ? CSS
    Append pointer-events: none class to the parent when the child is clicked. Append pointer-events: none class 在点击子项时发送给父项。 However, this would mean that the parent will need to be cleansed of the pointer-events class later.但是,这意味着稍后需要清除父对象的pointer-events class。

  2. Using Ref ?使用参考
    Record the ref of the parent React element & upon click on the child, compare the event.target against the ref?记录父React元素的ref并在单击子元素时,将event.target与 ref 进行比较? I don't like this because I don't like the global ref .我不喜欢这个,因为我不喜欢全局ref

Thoughts and the better solution would be much appreciated.想法和更好的解决方案将不胜感激。 The question is: How can I stop the event trigger on parent when the child is clicked?问题是:单击子项时如何停止父项上的事件触发器?

You can use stopPropagation您可以使用stopPropagation

stopPropagation - Prevents further propagation of the current event in the bubbling phase stopPropagation - 防止在冒泡阶段进一步传播当前事件

 var App = React.createClass({ handleParentClick: function (e) { console.log('parent'); }, handleChildClick: function (e) { e.stopPropagation(); console.log('child'); }, render: function() { return <div> <p onClick={this.handleParentClick}> <span onClick={this.handleChildClick}>Click</span> </p> </div>; } }); ReactDOM.render(<App />, document.getElementById('root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div>

I had the same issue in React and solved it using the solution bellow:我在 React 中遇到了同样的问题,并使用下面的解决方案解决了它:

if(e.currentTarget != e.target ) return;
.......

Another solution is to attach to the event callback on the parent the following:另一种解决方案是将以下内容附加到父级的事件回调:

if(event.target == event.currentTarget){
  event.stopPropagation()
  ....
}

This way you can intercept events, that originated in the attached DOM node and unrelated events are relayed to the next node.通过这种方式,您可以拦截源自附加 DOM 节点的事件,并将不相关的事件中继到下一个节点。

I wanted to invoke function on props but at the same time wanted to stop event propagation from child to parent, here is how its handled我想在道具上调用函数,但同时又想停止从孩子到父母的事件传播,这是它的处理方式

class LabelCancelable extends Component {

  handleChildClick(e) {
    e.stopPropagation()
  }
  closeClicked(e, props) {
    e.stopPropagation();
    props.onCloseClicked()
  }

  render() {
    const {displayLabel} = this.props;
    return (
      <span className={ "label-wrapper d-inline-block pr-2 pl-2 mr-2 mb-2" } onClick={ this.handleChildClick }>
          <button type="button" className="close cursor-pointer ml-2 float-right" aria-label="Close"
              onClick={(e) => this.closeClicked(e, this.props) }>
              <span aria-hidden="true">&times;</span>
          </button>
          <span className="label-text fs-12">
            { displayLabel }
          </span>
      </span>
    );
  }
}

export default LabelCancelable;

I find this solution the cleanest.我发现这个解决方案最干净。 Thank you @JohnFash!谢谢@JohnFash!

onClick={(event) => event.currentTarget == event.target && doSomething(event)}

Here is an attempt at explaining this in more details: when your mouse enters the parent element, the currentTarget is set (event), then when it enters the child element, the target changes.这里尝试更详细地解释这一点:当鼠标进入父元素时,currentTarget 被设置(事件),然后当它进入子元素时,目标发生变化。 If you don't do the check, the parent's onClick triggers because the mouseleave event hasn't triggered.如果您不进行检查,则父级的 onClick 将触发,因为 mouseleave 事件尚未触发。

Old question but had trouble then solved it myself I just stopped the event on the 'child' div like so this then passed down through children, so you can place where you want this to stop a click event;老问题但后来遇到了麻烦然后自己解决了我只是像这样停止了'child'div上的事件然后通过孩子传递下来,所以你可以把它放在你想要停止点击事件的地方;

<div onClick={doThisClickEvent}> 
 <div onClick={(e) => e.stopPropagation()}>
  <div>
   <p>This now wont trigger click event</p>
  </div>
 </div>
</div>


I had this problem with Material-UI DataGrid and solved it using this:我在使用 Material-UI DataGrid 时遇到了这个问题,并使用以下方法解决了这个问题:

event.defaultMuiPrevented = true;

eg:例如:

<DataGrid
  onCellDoubleClick={(params, event) => {
    if (!event.ctrlKey) {
      event.defaultMuiPrevented = true;
    }
  }}
  {...data}
/>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM