【问题标题】:React event handling together with plain JSReact 事件处理与普通 JS 一起
【发布时间】:2017-08-08 14:32:00
【问题描述】:

当我必须在一些我无法控制的代码中呈现 React 控件时,我遇到了一种情况。这是一个剑道 UI 网格,我需要在网格单元格中呈现自定义 React 组件。

Grid 是在底层使用 jQuery 创建的。它还为父 html 元素(在表格行上)添加了一个 click 事件侦听器。在我的 React 组件中,我还有一个 click 事件监听器。问题是附加到父级的处理程序首先触发。

下面的代码段(也可作为 fiddle 提供)演示了该问题。为了使这个示例尽可能简单,我只使用div 而不是 Kendo 网格。关键是我们在父 html 元素上有一个事件处理程序,然后我们使用其 click 处理程序将 React 组件渲染到此父元素中,并且父元素优先于 React。

class Btn extends React.Component {

  constructor(props) {
    super(props);

    this.click = this.click.bind(this);
  }

  click() {
    alert('Btn');
  }

  render() {
    return (
      <span onClick={this.click}>Click me</span>
    );
  }
};

$(function() {

  $('#container').on('click', function() {
    alert('JS');
  });

  ReactDOM.render(
    <Btn />,
    document.getElementById('btn')
  );

});
<div id="container">
  <div id="btn">
  </div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<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>

【问题讨论】:

  • 您可以将您的示例放在这里,现场作为可运行的堆栈片段;他们支持 React,包括 JSX; here's how to do one。这可能会帮助您获得答案。
  • (我继续为你做了。)
  • 你想同时保留这两个事件监听器吗?简单的解决方案可能是以编程方式删除困扰您的事件侦听器。顺便说一句,这可以帮助你:stackoverflow.com/a/1369080/5860648

标签: javascript reactjs events kendo-ui


【解决方案1】:

很不幸,但据我所知,你不能告诉 React 将其处理程序绑定在树的更深处(它使用document,然后使用来自那里的委托)。

要绕过它,您可以使用uncontrolled component(从Integrating with Other Libraries 链接)并使用ref 来连接您的处理程序:

首先我们设置参考:

<span ref={span => this.span = span}>Click me</span>

然后我们使用lifecycle methods 来添加和删除我们的处理程序:

componentDidMount() {
  this.span.addEventListener("click", this.click);
}

componentWillUnmount() {
  this.span.removeEventListener("click", this.click);
}

活生生的例子:

class Btn extends React.Component {

  constructor(props) {
    super(props);

    this.click = this.click.bind(this);
  }
  
  componentDidMount() {
    this.span.addEventListener("click", this.click);
  }
  
  componentWillUnmount() {
    this.span.removeEventListener("click", this.click);
  }

  click() {
    alert('Btn');
  }

  render() {
    return (
      <span ref={span => this.span = span}>Click me</span>
    );
  }
};

$(function() {

  $('#container').on('click', function() {
    alert('JS');
  });

  ReactDOM.render(
    <Btn />,
    document.getElementById('btn')
  );

});
<div id="container">
  <div id="btn">
  </div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<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>

(如果您需要支持没有addEventListener 的过时浏览器,请使用jQuery,或者如果您不希望依赖项this answer 具有用于挂钩事件的小型跨浏览器功能。您需要编写您的自己解开对应物。)

您甚至可以更进一步,只在您已安装组件的元素级别连接一个单击处理程序,并根据需要执行您自己的事件委托(或使用 jQuery)进行调度。

【讨论】:

  • 谢谢。我认为这正是我需要的,但我已经用纯 jQuery 做到了。组件非常简单,所以我只是手动完成了所有 html 创建和事件处理。
【解决方案2】:

这应该不再是 Kendo Grid for React 的本机实现的问题。由于网格正在侦听的事件是使用 React 而不是 jQuery 附加的,因此它们遵循 React 中的冒泡。因此,如果您愿意,您可以从孩子那里取消它们。 请参阅this demo 的来源,在自定义单元格中有一些自定义组件。

【讨论】:

    猜你喜欢
    • 2015-04-15
    • 2018-01-25
    • 2014-09-05
    • 2021-06-27
    • 2016-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多