防止双击被解释为两次单击?

时间:2018-02-16 20:14:22

标签: javascript reactjs javascript-events onclick event-handling

我有以下相当简单的React类:

import React from "react"

export default class DoubleClick extends React.Component {  

  constructor(props) {
    super(props);
    this.state = {
    };
    this.handleClick = this.handleClick.bind(this);
    this.handleDoubleClick = this.handleDoubleClick.bind(this);
  }
  handleClick() {
    console.log("Click");
  }
  handleDoubleClick() {
    console.log("Double Click");
  }
  render() {
    return (
      <div style={{backgroundColor: 'pink'}}>
          <div onClick={this.handleClick}> 
            <span onDoubleClick={this.handleDoubleClick}> Hello </span> 
            <span onDoubleClick={this.handleDoubleClick}> world. </span>
          </div>
      </div>
    );
  }
} 

当有人单击外部div时,我想调用handleClick,当有人双击我要调用handleDoubleClick的任何内部空间时,而不是{{1}对于外部div也是如此。

但是,每当我双击时,handleClick被调用, handleDoubleClick()也会被调用,即两次。

我只想在点击时调用handleClick,但双击 - 这可能吗?

2 个答案:

答案 0 :(得分:2)

我有一个HOC用于估算您正在寻找的内容:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class DoubleClick extends Component {
  constructor(props) {
    super(props);
    this.onClick = this.onClick.bind(this);
    this.onDoubleClick = this.onDoubleClick.bind(this);
    this.timeout = null;
  }

  onClick(e) {
    e.preventDefault();

    if(this.timeout === null) {
      this.timeout = window.setTimeout(() => {
        this.timeout = null;
        this.props.onClick();
      }, 300);
    }
  }

  onDoubleClick(e) {
    e.preventDefault();
    window.clearTimeout(this.timeout);
    this.timeout = null;
    this.props.onDoubleClick();
  }

  render() {
    const { onClick, onDoubleClick, children, ...childProps } = this.props;
    const props = Object.assign(childProps, { onClick: this.onClick, onDoubleClick: this.onDoubleClick });
    return React.cloneElement(children, props);
  }
}

DoubleClick.propTypes = {
  onClick: PropTypes.func.isRequired,
  onDoubleClick: PropTypes.func.isRequired,
  children: PropTypes.element.isRequired,
};

像这样使用:

<DoubleClick onClick={clickHandler} onDoubleClick={doubleClickHandler}>
  <button>Click or double click me</button>
</DoubleClick>

收到第一次点击后,会设置300毫秒超时。如果在300毫秒内没有收到第二次点击,将调用onClick道具中的函数。如果在300毫秒内收到第二次点击,将调用onDoubleClick道具中的函数,并取消超时,以便onClick不会触发。

毋庸置疑,这是一个不完美的近似,但我发现它在实践中是一种足够令人满意的用户体验。

答案 1 :(得分:0)

就像其他人所说的那样,不能在没有超时的情况下对孩子进行双击(我认为),对父母点击事件是不可能的。

如果您可以牺牲500毫秒的UX部分,直到点击被识别为非双击,您可以使用超时。

constructor(props) {
    super(props);
    this.state = {
    };
    this.handleClick = this.handleClick.bind(this);
    this.handleDoubleClick = this.handleDoubleClick.bind(this);

    // hack doubleclick
    this.doubleClickTimeout = 500; // default doubleclick timeout
    this.clickedTimeout = null;
  }
  handleClick(ev) {
    if (!this.clickedTimeout) {
      this.clickedTimeout = setTimeout(() => {
        this.clickedTimeout = null;
        // do your stuff here
        console.log('Clicked');
      }, this.doubleClickTimeout);
    }


  }
  handleDoubleClick() {
    clearTimeout(this.clickedTimeout);
    this.clickedTimeout = null;
    console.log("Double Click");

  }
  render() {
    return (
      <div style={{backgroundColor: 'pink'}}>
          <div onClick={this.handleClick}>
            <span onDoubleClick={this.handleDoubleClick}> Hello </span>
            <span onDoubleClick={this.handleDoubleClick}> world. </span>
          </div>
      </div>
    );
  }