单击时React阻止事件在嵌套组件中冒泡

reactjs React.js

理查德小哥

2020-03-12

这是一个基本组成部分。无论是<ul><li>拥有的onClick功能。我只希望<li>触发onClick 而不触发<ul>我该如何实现?

我玩过e.preventDefault(),e.​​stopPropagation()都无济于事。

class List extends React.Component {
  constructor(props) {
    super(props);
  }

  handleClick() {
    // do something
  }

  render() {

    return (
      <ul 
        onClick={(e) => {
          console.log('parent');
          this.handleClick();
        }}
      >
        <li 
          onClick={(e) => {
            console.log('child');
            // prevent default? prevent propagation?
            this.handleClick();
          }}
        >
        </li>       
      </ul>
    )
  }
}

// => parent
// => child

第1171篇《单击时React阻止事件在嵌套组件中冒泡》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

6个回答
鸣人 2020.03.12

我在event.stopPropagation()上班时遇到问题如果您也这样做,请尝试将其移至点击处理程序函数的顶部,这是我阻止事件冒泡所需的操作。示例功能:

  toggleFilter(e) {
    e.stopPropagation(); // If moved to the end of the function, will not work
    let target = e.target;
    let i = 10; // Sanity breaker

    while(true) {
      if (--i === 0) { return; }
      if (target.classList.contains("filter")) {
        target.classList.toggle("active");
        break;
      }
      target = target.parentNode;
    }
  }
逆天L 2020.03.12

您可以通过检查事件目标来避免事件冒泡。
例如,如果您将输入嵌套到div元素中,而该元素具有单击事件的处理程序,并且您不想处理该事件,则在单击输入时,您可以传递event.target到处理程序中,并检查是否应基于以下命令执行处理程序目标的属性。
例如,您可以检查if (target.localName === "input") { return}
因此,这是“避免”处理程序执行的一种方式

宝儿Near 2020.03.12

这样做的新方法要简单得多,并且可以节省您一些时间!只需将事件传递到原始点击处理程序并致电即可preventDefault();

clickHandler(e){
    e.preventDefault();
    //Your functionality here
}
神无村村 2020.03.12

我遇到过同样的问题。我发现stopPropagation 确实有效。我将列表项拆分为一个单独的组件,如下所示:

class List extends React.Component {
  handleClick = e => {
    // do something
  }

  render() {
    return (
      <ul onClick={this.handleClick}>
        <ListItem onClick={this.handleClick}>Item</ListItem> 
      </ul>
    )
  }
}

class ListItem extends React.Component {
  handleClick = e => {
    e.stopPropagation();  //  <------ Here is the magic
    this.props.onClick();
  }

  render() {
    return (
      <li onClick={this.handleClick}>
        {this.props.children}
      </li>       
    )
  }
}
JinJin猪猪 2020.03.12

这是不是100%完美,但如果它要么是太痛苦的向下传递props的孩子- >儿童时装或创建Context.Provider/ Context.Consumer 用于此目的),而你处理的是有它自己的处理器运行的另一个库在您之前,您还可以尝试:

   function myHandler(e) { 
        e.persist(); 
        e.nativeEvent.stopImmediatePropagation();
        e.stopPropagation(); 
   }

据我所知,该event.persist方法可以防止将对象立即扔回React的SyntheticEvent池中。因此,因此,在您event获得React时传递的React实际上并不存在!这是在子孙中发生的,这是因为React首先通过在SyntheticEvent处理过程中检查父对象(特别是如果父对象具有回调)来在内部处理事情的方式

只要您不调用persist会创建大量内存的东西来继续创建事件(例如,onMouseMove并且您未在创建某种Cookie Clicker游戏,例如奶奶的Cookies),就应该完美!

还要注意:从偶尔阅读他们的GitHub来看,我们应该对React的未来版本保持警惕,因为他们最终可能会解决一些麻烦,因为他们似乎打算在编译器/编译器中折叠React代码。

猴子Davaid神乐 2020.03.12

React使用事件委派和文档上的单个事件侦听器来处理冒泡的事件,例如本示例中的“单击”,这意味着无法停止传播;当您在React中与真实事件互动时,真实事件已经传播了。由于React在内部处理合成事件的传播,因此可以对React的合成事件进行stopPropagation。

stopPropagation: function(e){
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
}

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android