【问题标题】:React component onClick handler not working反应组件 onClick 处理程序不起作用
【发布时间】:2016-09-12 13:44:46
【问题描述】:

我有一个基本的弹出窗口(图像),当您单击按钮时会出现。当您在该弹出窗口之外单击时,它应该关闭,但是当您在其中单击时,它应该保持打开状态并调用测试功能。它的初始状态 isPopupVisible 设置为 false。当您单击按钮时,我将状态设置为 true 以呈现弹出窗口。

问题是单击图像时未调用测试函数。我认为这是因为状态设置为 false 并且具有 onClick 函数的图像元素最初没有呈现。有谁知道如何解决这个问题?

(用 ecmascript 6 编写)

getInitialState () {
  return {isPopupVisible: false}
},
onClick () {
  if(!this.state.isPopupVisible){
    this.setState({isPopupVisible: true});
    document.body.addEventListener('click', this.onClickBody)
  }
},
onClickBody () {
  this.setState({isPopupVisible: false});
  document.body.removeEventListener('click', this.onClickBody)
},
test () {
  console.log('the onClick from the image works!');
},
showPopup () {
  if(this.state.isPopupVisible){
    return <div>
      <img src='img.png' onClick={this.test} />
    </div>
  }else{
    return null;
  }
},
render () {
  return (
    <span>
      <button onClick={this.onClick}>
        See Popup
      </button>
      {this.showPopup()}
    </span>
  );
}

【问题讨论】:

  • 点击kng的时候或者点击之前没有控制台报错吗?
  • 页面加载或点击图片时没有错误。为了测试它,我将 this.state.isPopupVisible 设为 true,并且 onClick 有效。我只是不明白为什么它最初不渲染时不起作用。

标签: javascript event-handling reactjs


【解决方案1】:

这有点小题大做,但是...

onClickBody () {
  setTimeout(function(){
    if (!this.clickedInBounds && this.isMounted()) {
      this.setState({isPopupVisible: false});
      document.body.removeEventListener('click', this.onClickBody)
    }
    this.clickedInBounds = false;    
  }.bind(this), 0);
},
test () {
  console.log('the onClick from the image works!');
  this.clickedInBounds = true;
},

setTimeout 只是为了让它在test 有机会运行之后运行该代码。 isMounted 只是为了在点击 body 和 setTimeout 之间卸载组件的可能性很小。

jsbin

【讨论】:

  • 非常感谢@FakeRainBrigand!这有点hacky,但这是我迄今为止唯一能做的事情。感谢您的帮助:)
【解决方案2】:

除了在body 上添加click 侦听器之外,您还可以在呈现弹出窗口之前添加一个底层透明 div,该 div 会在单击时关闭弹出窗口。

例如,这是在react-bootstrap 模态组件中的实现方式:https://github.com/react-bootstrap/react-bootstrap/blob/master/src/Modal.jsx#L73

您可以在这里查看演示:http://react-bootstrap.github.io/components.html#modals

【讨论】:

    【解决方案3】:

    您的onClickBody 处理程序在test 被调用之前被调用,在合成事件触发之前更改状态并从虚拟DOM 中删除图像。

    可能有一个优雅的方法来解决这个问题,但是因为您正在混合原生和 React 事件 API,我猜您必须更改 onClickBody 的签名以将事件作为其第一个参数,然后包装方法的主体类似于if (e.target.nodeName !== "IMG") {}

    JSFiddle 在这里展示了这一点:http://jsfiddle.net/reactjs/69z2wepo/

    【讨论】:

      【解决方案4】:

      我知道这篇文章已经过了一年,但我知道正确的答案。

      你有很多引用危险。

      onClick () {
        var self = this;
        if(!this.state.isPopupVisible){
          self .setState({isPopupVisible: true});
          document.body.addEventListener('click', self .onClickBody)
        }
      },
      onClickBody () {
        var self = this;
        this.setState({isPopupVisible: false});
        document.body.removeEventListener('click', self .onClickBody)
      },
      test () {
        console.log('the onClick from the image works!');
      },
      showPopup () {
        var self = this;
        if(this.state.isPopupVisible){
          return <div>
            <img src='img.png' onClick={self.test} />
          </div>
        }else{
          return null;
        }
      },
      

      这肯定能解决您的问题

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-16
        • 1970-01-01
        相关资源
        最近更新 更多