【问题标题】:React onClick and onTouchStart fired simultaneouslyReact onClick 和 onTouchStart 同时触发
【发布时间】:2021-12-30 05:20:46
【问题描述】:

我的 React 应用程序中有一个 div,我需要同时处理点击和触摸。但是,当我点击移动设备时,它会触发这两个事件。

如果我在手机上滑动或点击普通浏览器,它可以正常工作,每种情况下只会触发一个事件。

如何处理此点击问题以不触发这两个事件?

<div
  className={myClasses}
  onClick={this.myHandle}
  onTouchStart={this.myHandle}
  >&nbsp;
</div>

【问题讨论】:

  • 为什么需要 TouchStart 和 click?移动设备和桌面设备都将调用 click。生命周期通常是:touchstart (mousedown) -> touchend (mouseup) -> click。所以除非你需要为 touchstart 做一些明确的事情,否则我会放弃它。
  • 我明白你的意思。我之前只有一个,但是,如果用户滑动,它不会触发点击,只会触发触摸事件。这是一种轮播,用户可以点击或滑动“下一张卡片”以滑动。
  • 我对这些控件的所有经验都告诉我这些控件不会同时触发??你确定你正确地分析了情况吗? event.preventDefault() 在这里对你有帮助吗?
  • @Shammoo 我的意思是它们是用相同的鼠标动作触发的。当我点击时,两个事件都会被触发,首先是onTouchStart,然后是onClick。我的句柄this.myHandle 改变了状态,所以组件再次渲染。第二个事件(点击)仍然会触发。
  • 对于那些在未来发现它的人:这就是它应该做的。 onClick 不是“鼠标”事件,它是“点击”事件,相当于触摸设备上的“touchStart-followed-by-touchEnd`。所以在触摸设备上,touchstart 触发,调用处理程序, touchend 触发,没有处理程序,然后click 触发,再次调用处理程序。只需删除 onTouchStart,就完成了。

标签: javascript reactjs


【解决方案1】:

事件触发的时间已定义(source):

touchstart
Zero or more touchmove events, depending on movement of the finger(s)
touchend
mousemove
mousedown
mouseup
click

如果您想在之前触发触摸事件的情况下阻止click 事件,您可以在touchend event handler 中使用event.preventDefault() 来阻止click 事件触发。

function App() {
  const handleClick = () => {
    alert('click');
  };

  const handleTouchEnd = (event) => {
    alert('touchend');

    event.preventDefault();
  };

  return (
    <button
      type="button"
      onClick={handleClick}
      onTouchEnd={handleTouchEnd}
    >
      Click Me
    </button>
  );
}

但是,这并不是普遍适用的。例如,您不能通过在mousedown 事件中使用event.preventDefault()preventclick 事件。如果您正在寻找解决方案(但不确定此用例何时适用),则必须改用 ref

function App() {
  const prevent = React.useRef(false);

  const handleClick = () => {
    if (!prevent.current) {
      alert('click');
    } else {
      prevent.current = false;
    }
  };

  const handleMouseDown = () => {
    prevent.current = true;

    alert('mousedown');
  };

  return (
    <button
      type="button"
      onClick={handleClick}
      onMouseDown={handleMouseDown}
    >
      Click Me
    </button>
  );
}

【讨论】:

  • 在 React 中,我必须使用 event.stopPropagation() 来阻止它同时触发 onTouchStartonMouseDown
【解决方案2】:

使用触摸和鼠标之间的类似事件解决了这个问题。 touchStart/mouseDown 或 touchEnd/mouseUp。它会根据每种情况触发一个或另一个。

<div
  className={myClasses}
  onMouseUp={this.myHandle}
  onTouchEnd={this.myHandle}
  >&nbsp;
</div>

【讨论】:

    【解决方案3】:

    为避免在触摸设备上出现onClick(),您应该检查页面是否在触摸设备中打开。

    检查天气是否在触摸设备中打开:

    if (typeof document !== 'undefined') {
      var isTouch = 'ontouchstart' in document.documentElement;
    }
    

    然后将{isTouch ? undefined : this.myHandle}修改为你的鼠标事件:

    <div
      className={myClasses}
      onClick={isTouch ? undefined : this.myHandle}
      onTouchStart={this.myHandle}
      >&nbsp;
    </div>
    

    【讨论】:

      【解决方案4】:

      这晚了几年,但找到了一个非常容易实施的解决方案。看起来像这样:

      import ReactDom from 'react-dom';
      
      export default class YourClass extends Component {
      
      componentDidMount(){
              ReactDOM.findDOMNode(this).addEventListener('touchstart', (e)=>{ 
                  e.preventDefault(); 
                  console.log("touchstart triggered");
              });
          }
      }
      

      似乎它拦截并停止了移动设备上的所有 onClick 调用,这正是我想要的

      【讨论】:

        猜你喜欢
        • 2014-02-26
        • 2020-11-28
        • 2021-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-05
        相关资源
        最近更新 更多