Javascript onClick 有效但 onDoubleClick 在 React 组件上被忽略

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25777826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 21:51:31  来源:igfitidea点击:

onClick works but onDoubleClick is ignored on React component

javascriptreactjs

提问by thisisnotabus

I am building a Minesweeper game with React and want to perform a different action when a cell is single or double clicked. Currently, the onDoubleClickfunction will never fire, the alert from onClickis shown. If I remove the onClickhandler, onDoubleClickworks. Why don't both events work? Is it possible to have both events on an element?

我正在使用 React 构建扫雷游戏,并希望在单击或双击单元格时执行不同的操作。目前,该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'));

采纳答案by Ross Allen

This is not a limitation of React, it is a limitation of the DOM's clickand dblclickevents. As suggested by Quirksmode's click documentation:

这不是 React 的限制,而是 DOMclickdblclick事件的限制。正如 Quirksmode 的点击文档所建议的:

Don't register click and dblclick events on the same element: it's impossible to distinguish single-click events from click events that lead to a dblclick event.

不要在同一个元素上注册 click 和 dblclick 事件:无法区分单击事件和导致 dblclick 事件的单击事件。

For more current documentation, the W3C spec on the dblclickeventstates:

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

A user agent must dispatch this event when the primary button of a pointing device is clicked twice over an element.

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

A double click event necessarily happens after two click events.

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

Edit:

编辑

One more suggested read is jQuery's dblclickhandler:

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

It is inadvisable to bind handlers to both the click and dblclick events for the same element. The sequence of events triggered varies from browser to browser, with some receiving two click events before the dblclick and others only one. Double-click sensitivity (maximum time between clicks that is detected as a double click) can vary by operating system and browser, and is often user-configurable.

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

回答by Akanksha Chaturvedi

The required result can be achieved by providing a very slight delay on firing off the normal click action, which will be cancelled when the double click event will happen.

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

  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>

回答by Jeff Fairley

Edit:

编辑:

I've found that this is not an issue with React 0.15.3.

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



Original:

原来的:

For React 0.13.3, here are two solutions.

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

1. ref callback

1. ref 回调

Note, even in the case of double-click, the single-click handler will be called twice (once for each click).

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

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 debounce

2. lodash 去抖动

I had another solution that used lodash, but I abandoned it because of the complexity. The benefit of this was that "click" was only called once, and not at all in the case of "double-click".

我有另一个使用 的解决方案lodash,但由于复杂性我放弃了它。这样做的好处是“点击”只被调用一次,而在“双击”的情况下根本没有。

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;

on the soapbox

在肥皂盒上

I appreciate the idea that double-click isn't something easily detected, but for better or worse it ISa paradigm that exists and one that users understand because of its prevalence in operating systems. Furthermore, it's a paradigm that modern browsers still support. Until such time that it is removed from the DOM specifications, my opinion is that React should support a functioning onDoubleClickprop alongside onClick. It's unfortunate that it seems they do not.

我很欣赏的想法,双击是不容易发现的东西,但是是好还是坏它IS存在和一个用户理解,因为它在操作系统中流行的一个范例。此外,它是现代浏览器仍然支持的范例。在它从 DOM 规范中删除之前,我的观点是 React 应该支持一个功能性的onDoubleClickprop 和onClick. 不幸的是,他们似乎没有。

回答by Alex Mireles

Here's what I have done. Any suggestions for improvement are welcome.

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

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>
   </>
  )
 }
}