与普通JS一起反应事件处理

时间:2017-08-08 14:32:00

标签: javascript reactjs events kendo-ui

我有一种情况,我必须在一些我无法控制的代码中呈现React控件。它是一个kendo UI网格,我需要在网格单元格中渲染自定义的React组件。

Grid是使用jQuery创建的。它还为父html元素(在表行上)添加了<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>About</title> <script type="text/javascript"> function val1(val) { document.getElementsByTagName("div")[0].setAttribute("data-video", val); alert(val); } </script> </head> <body onload="val1('WKV_z36pVAk')"> <h3 style="color:#0066dd">Hello</h3> <center> <div data-video="8IYzyTYucKQ" data-autoplay="0" data-loop="1" id="youtube-audio"> </div> </center> <button>change</button> </body> <script src="https://www.youtube.com/iframe_api"></script> <script src="https://cdn.rawgit.com/labnol/files/master/yt.js"></script> </html> 事件侦听器。在我的React组件中,我还有一个click事件监听器。问题是附加到父级的处理程序首先触发。

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

&#13;
&#13;
click
&#13;
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')
  );

});
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

这很不幸,但是我尽可能地告诉你不能告诉React将其处理程序绑定在树的更深处(它使用document,然后使用委托)。

要绕过它,你会做一种uncontrolled component(来自Integrating with Other Libraries的链接)并使用ref来挂钩你的处理程序:

首先我们设置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具有用于挂钩事件的小型跨浏览器功能。需要编写自己的unhook对应物。)

您甚至可以更进一步,只在您安装组件的元素级别挂钩单击处理程序,并根据需要执行您自己的事件委托(或使用jQuery)进行分派。 p>

答案 1 :(得分:0)

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