长按按钮反应

Long Press button in react

这可能真的很简单,但任何人都知道如何在 React 中制作长按按钮。就像一个按钮,如果你按住它 2 秒,它就会被“点击”,否则就不会。是否有反应鼠标事件?也许我以某种巧妙的方式使用了 onMouseDown 事件?

您可以尝试的一种技巧是记下 'onMouseDown' 事件触发的时间,并记下 'onMouseUp' 事件触发的时间。

如果这些时间之间的差异大于等于 2 秒,您可以执行您想要的操作。

您必须在 'onMouseUp' 事件触发时执行的方法中编写逻辑来检查时差和要执行的代码。

delay = 2000;
startPress = null;

function mouseDown() {
    startPress = Date.now();
}

function mouseUp() {
    if(Date.now() - startPress > delay)
    {
        // your code
    }
}

我使用以下方法创建了一个按钮,当您按住该按钮时,该按钮会动态变化 class。使用 setInterval 而不是 setTimeout 可以简化操作,因为我们自己管理结束计数。我们不做任何类型的 DateTime 计算,我们可以通过观察 currentCount.

主动监控当前延迟毫秒数

我使用 DaisyUI 作为我的组件框架,但是任何 CSS classes 都可以使用。

import { useCallback, useEffect, useRef, useState } from 'react';

export type LongPressButtonProps = {
  /** Text that will appear within the button */
  buttonText: string;
  /** Function to run once delay has been exceeded */
  onExecute: () => void;
  /** How long should be button be held before firing onExecute */
  delayMs: number;
  /** How frequently should the count be updated */
  refreshMs: number;
};

const LongPressButton = ({
  delayMs,
  onExecute,
  buttonText,
  refreshMs = 100,
}: LongPressButtonProps) => {
  const [mouseDown, setMouseDown] = useState(false);
  const [currentCount, setCurrentCount] = useState(0);
  const intervalRef = useRef<NodeJS.Timer>();
  const [buttonClass, setButtonClass] = useState('btn-primary');

  const onInterval = useCallback(() => {
    setCurrentCount((c) => c + refreshMs);
  }, [setCurrentCount, refreshMs]);

  useEffect(() => {
    if (mouseDown) intervalRef.current = setInterval(onInterval, refreshMs);

    if (!mouseDown && intervalRef.current) {
      clearInterval(intervalRef.current);
      setCurrentCount(0);
      setButtonClass(`btn-primary`);
    }
  }, [onInterval, delayMs, mouseDown, refreshMs]);

  useEffect(() => {
    if (currentCount > 0) setButtonClass(`btn-error`);
    if (currentCount > delayMs) {
      onExecute();
      setCurrentCount(0);
    }
  }, [currentCount, delayMs, onExecute]);

  return (
    <button
      className={`btn ${buttonClass}`}
      onMouseDown={() => setMouseDown(true)}
      onMouseUp={() => setMouseDown(false)}
      onMouseLeave={() => setMouseDown(false)}
      onTouchStart={() => setMouseDown(true)}
      onTouchEnd={() => setMouseDown(false)}
      style={{ transition: `${delayMs}ms` }}
    >
      {buttonText}
    </button>
  );
};

export default LongPressButton;