事件冒泡预防无效'在React js

时间:2018-04-14 14:57:49

标签: javascript reactjs javascript-events event-handling

我一直在React的活动系统的舒适范围内探索一些事件处理,并了解它如何与外部' DOM中的世界。

实施例

这是我正在试验的注释样本:

class FunWithEvents extends Component {
  handleKeyUpWithoutReact(e) {
    console.warn('OMG I handled an event without React ');
    // I noticed that `e.cancelBubble` is `true` here...
  }

  handleKeyUpParent(e) {
    // This handler appears to be under React's supervision...
    console.info('I get prevented :)');
  }

  handleKeyUpTarget(e) {
    console.info("I'm shown in the console :)");
    e.stopPropagation();
  }

  componentDidMount() {
    document.addEventListener('keyup', this.handleKeyUpWithoutReact);
  }

  componentWillUnmount() {
    document.removeEventListener('keyup', this.handleKeyUpWithoutReact);
  }

  render() {
    return (
      <div onKeyUp={(e) => this.handleKeyUpParent(e)}>
        <input onKeyUp={(e) => this.handleKeyUpTarget(e)} />
      </div>
    );
  }
}

正如支持的注释所希望的那样,我注意到了:

  1. 事件冒泡之旅的开始/目标,从input开始,确实按照我的预期触发了handleKeyUpTarget处理程序。
  2. 我们通过e.stopPropagation内的handleKeyUpTarget防止进一步冒泡。
  3. 作为第2点的结果,防止冒泡,handleKeyUpParent处理程序按照我的预期运行。
  4. 但是,handleKeyUpWithoutReact 被调用。这让我措手不及,正确或(可能)错误。
  5. 我的问题

    • 为什么React不会阻止使用e.stopPropagation()冒泡的本机事件?这是设计用于与共享环境的互操作性吗?
    • 如果这完全是设计的,我是否可以依赖cancelBubble设置为true,如handleKeyUpWithoutReact方法所示?

    提前致谢!

    环境

    • 反应16.3.1
    • react-dom 16.3.1
    • Chrome 65.0.3325.181

1 个答案:

答案 0 :(得分:1)

event.stopPropagation()仅停止传播到React中附加的事件。例如,onKeyUponChangeonClick等上的事件都是React中的合成事件,并且为了使用document.addEventListener附加的外部事件停止传播,您需要使用nativeEvent并运行e.nativeEvent.stopImmediatePropagation();

class FunWithEvents extends React.Component {
  handleKeyUpWithoutReact(e) {
    console.warn("OMG I handled an event without React ");
    // I noticed that `e.cancelBubble` is `true` here...
  }

  handleKeyUpParent(e) {
    // This handler appears to be under React's supervision...
    console.info("I get prevented :)");
  }

  handleKeyUpTarget(e) {
    console.info("I'm shown in the console :)");
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
  }

  componentDidMount() {
    document.addEventListener("keyup", this.handleKeyUpWithoutReact);
  }

  componentWillUnmount() {
    document.removeEventListener("keyup", this.handleKeyUpWithoutReact);
  }

  render() {
    return (
      <div onKeyUp={e => this.handleKeyUpParent(e)}>
        <input onKeyUp={e => this.handleKeyUpTarget(e)} />
      </div>
    );
  }
}

<强> Working DEMO