javascript-onClick可以运行,但是onDoubleClick在React组件上被忽略

我正在使用React构建Minesweeper游戏,并且希望在单击单元格或双击单元格时执行其他操作。 当前,onDoubleClick函数将永远不会触发,显示onClick的警报。 如果我卸下onClick处理程序,则onDoubleClick可以工作。 为什么两个事件都不起作用? 是否可以在一个元素上同时存在两个事件?

/** @jsx React.DOM */

var Mine = React.createClass({
  render: function(){
    return (
      <div className="mineBox" id={this.props.id} onDoubleClick={this.props.onDoubleClick} onClick={this.props.onClick}></div>
    )
  }
});

var MineRow = React.createClass({
  render: function(){
    var width = this.props.width,
        row = [];
    for (var i = 0; i < width; i++){
      row.push(<Mine id={String(this.props.row + i)} boxClass={this.props.boxClass} onDoubleClick={this.props.onDoubleClick} onClick={this.props.onClick}/>)
    }
    return (
      <div>{row}</div>
    )
  }
})

var MineSweeper = React.createClass({
  handleDoubleClick: function(){
    alert('Double Clicked');
  },
  handleClick: function(){
    alert('Single Clicked');
  },
  render: function(){
    var height = this.props.height,
        table = [];
    for (var i = 0; i < height; i++){
      table.push(<MineRow width={this.props.width} row={String.fromCharCode(97 + i)} onDoubleClick={this.handleDoubleClick} onClick={this.handleClick}/>)
    }
    return (
      <div>{table}</div>
    )
  }
})

var bombs = ['a0', 'b1', 'c2'];
React.renderComponent(<MineSweeper height={5} width={5} bombs={bombs}/>, document.getElementById('content'));
thisisnotabus asked 2020-01-11T21:05:32Z
4个解决方案
49 votes

这不是React的限制,它是DOM的dblclickdblclick事件的限制。 如Quirksmode的click文档所建议:

不要在同一元素上注册click和dblclick事件:不可能将单击事件与导致dblclick事件的单击事件区分开。

有关最新的文档,在dblclick事件上的W3C规范指出:

当定点设备的主按钮在某个元素上单击两次时,用户代理必须调度此事件。

双击事件必然在两次单击事件之后发生。

编辑:

建议阅读的另一种方法是jQuery的dblclick处理程序:

将处理程序绑定到同一元素的click和dblclick事件都是不可取的。 触发事件的顺序因浏览器而异,其中一些事件在dblclick之前收到两个click事件,而其他事件仅收到一个。 双击灵敏度(检测为两次单击之间的最长间隔时间)可能因操作系统和浏览器而异,并且通常可由用户配置。

Ross Allen answered 2020-01-11T21:06:23Z
16 votes

可以通过在触发常规单击操作时提供非常小的延迟来实现所需的结果,当发生双击事件时,该延迟将被取消。

  let timer = 0;
  let delay = 200;
  let prevent = false;

  doClickAction() {
    console.log(' click');
  }
  doDoubleClickAction() {
    console.log('Double Click')
  }
  handleClick() {
    let me = this;
    timer = setTimeout(function() {
      if (!prevent) {
        me.doClickAction();
      }
      prevent = false;
    }, delay);
  }
  handleDoubleClick(){
    clearTimeout(timer);
    prevent = true;
    this.doDoubleClickAction();
  }
 < button onClick={this.handleClick.bind(this)} 
    onDoubleClick = {this.handleDoubleClick.bind(this)} > click me </button>
Akanksha Chaturvedi answered 2020-01-11T21:06:43Z
13 votes

编辑:

我发现这不是React 0.15.3的问题。


原版的:

对于React 0.13.3,这是两个解决方案。

1. ref回调

请注意,即使在双击的情况下,单击处理程序也会被调用两次(每次单击一次)。

const ListItem = React.createClass({

  handleClick() {
    console.log('single click');
  },

  handleDoubleClick() {
    console.log('double click');
  },

  refCallback(item) {
    if (item) {
      item.getDOMNode().ondblclick = this.handleDoubleClick;
    }
  },

  render() {
    return (
      <div onClick={this.handleClick}
           ref={this.refCallback}>
      </div>
    );
  }
});

module.exports = ListItem;

2. lodash跳动

我还有一个使用onDoubleClick的解决方案,但是由于复杂性,我放弃了它。 这样做的好处是“ click”仅被调用一次,而在“ double-click”情况下则根本不被调用。

import _ from 'lodash'

const ListItem = React.createClass({

  handleClick(e) {
    if (!this._delayedClick) {
      this._delayedClick = _.debounce(this.doClick, 500);
    }
    if (this.clickedOnce) {
      this._delayedClick.cancel();
      this.clickedOnce = false;
      console.log('double click');
    } else {
      this._delayedClick(e);
      this.clickedOnce = true;
    }
  },

  doClick(e) {
    this.clickedOnce = undefined;
    console.log('single click');
  },

  render() {
    return (
      <div onClick={this.handleClick}>
      </div>
    );
  }
});

module.exports = ListItem;

在肥皂盒上

我很欣赏双击不是很容易被发现的想法,但是无论好坏,它都是存在的一种范例,并且由于其在操作系统中的盛行,用户可以理解。 此外,这是现代浏览器仍支持的范例。 在将其从DOM规范中删除之前,我的观点是React应该与onClick一起支持功能正常的onDoubleClick道具。不幸的是,似乎他们没有。

Jeff Fairley answered 2020-01-11T21:07:43Z
1 votes

这就是我所做的。 欢迎提出任何改进建议。

class DoubleClick extends React.Component {
  state = {counter: 0}

  handleClick = () => {
   this.setState(state => ({
    counter: this.state.counter + 1,
  }))
 }


  handleDoubleClick = () => {
   this.setState(state => ({
    counter: this.state.counter - 2,
  }))
 }

 render() {
   return(
   <>
    <button onClick={this.handleClick} onDoubleClick={this.handleDoubleClick>
      {this.state.counter}
    </button>
   </>
  )
 }
}
Alex Mireles answered 2020-01-11T21:08:03Z
translate from https://stackoverflow.com:/questions/25777826/onclick-works-but-ondoubleclick-is-ignored-on-react-component