React,如何阻止拖动后执行点击事件?

问题描述 投票:0回答:6

我有 Draggable 元素,在它的内部,我有一个带有 onClick 事件的组件。拖动结束时,触发点击事件。 我的可拖动元素如下所示。我使用了一个名为 react-draggable 的包。

<Draggable
    position={this.state.realPosition}
    onStart={this.handleStart}
    onDrag={this.handleDrag}
    onStop={this.handleStop}
    disabled={this.state.isDialogOpen}
    bounds="parent">
      <div style={{"width":"fit-content"}}>
        <Helmet getDialogStatus={this.handleClick} />  
      </div>
</Draggable>

我在 Helmet 组件内有 onClick 事件,它会打开一个对话框。当我拖动并释放该元素时,将打开此对话框。我的问题是如何防止此操作以及如何将这些操作与事件分开?

谢谢。

reactjs onclick drag-and-drop draggable
6个回答
4
投票
const [isDragging, setIsDragging] = useState<any>(false);

const eventControl = (event: { type: any; }, info: any) => {


    if (event.type === 'mousemove' || event.type === 'touchmove') {
      setIsDragging(true)
    }

    if (event.type === 'mouseup' || event.type === 'touchend') {
      setTimeout(() => {
        setIsDragging(false);
      }, 100);

    }
  }

然后,

<Draggable
    bounds="parent"
    onDrag={eventControl}
    onStop={eventControl}
> ...

2
投票

我会在持有

Draggable
isDragging
的组件中设置一个状态,并将其传递给头盔组件。

如果 isDragging 则禁用任何点击事件。


1
投票

您可以通过使用状态变量 isDragging 来跟踪组件是否被拖动来区分拖动和单击。使用react-draggable组件的onDrag和onStop事件来管理此状态。这是一种有效的方法,感谢 @lakjeewaWijebandara

const [isDragging, setIsDragging] = useState(false);

const eventControl = (event) => {
   if (event.type === "mousemove" || event.type === "touchmove") {
     setIsDragging(true);
   }

   if (event.type === "mouseup" || event.type === "touchend") {
     setTimeout(() => {
       setIsDragging(false);
     }, 100);
   }
 };

return (
   <Draggable bounds="parent" onDrag={eventControl} onStop={eventControl}>
     <div
        onClick={() => !isDragging && handleOpen()}
        onTouchEnd={() => !isDragging && handleOpen()}
     >
       // Button content here ...
     </div>
   </Draggable>
);

在该方案中,当检测到mousemove或touchmove事件时,isDragging被设置为true,表示进行拖动操作。当检测到 mouseup 或 touchend 事件时,isDragging 在一小段延迟后被设置为 false,表示拖动操作已结束。单击或触摸按钮时,仅当 isDragging 为 false 时才会调用handleOpen 函数,以确保在拖动操作期间不会触发该函数。


0
投票

尝试通过使用事件对象在

event.stopPropagation();
this.handleDrag
事件处理程序中使用
this.handleStop
。他们可能会解决您的问题。


0
投票

创建一个引用来跟踪鼠标指针的 x 和 y 位置。如果位置发生了一定阈值的变化,那么我们可以认为鼠标正在拖动,否则就是单击。

const pointer = useRef({x: 0, y: 0});

const onMouseDown = (e) => {
    pointer.current = {x: e.clientX, y: e.clientY};
}

const onMouseUp = (e) => {
    const {x, y} = pointer.current;
    if (Math.abs(e.clientX - x) < 10 && Math.abs(e.clientY - y) < 10) {
        // your click function here
    }
}

然后在特定的div上添加onMouseDown和onMouseUp事件

<div onMouseDown={onMouseDown} onMouseUp={onMouseUp}>{...}</div>

0
投票

为了防止在 React 中拖动 div 中的元素后触发单击事件,可以使用区分“单击”和“拖动”的技术。单击是一种鼠标事件,在用户按下(mousedown)和释放(mouseup)鼠标按钮之间没有明显的移动。阻力涉及这两个事件之间的位移。

其想法是在 mousedown 事件中记录鼠标坐标,并将其与 mouseup 事件中的鼠标坐标进行比较。如果坐标之间的距离大于某个阈值(比如几个像素),就认为是拖动,可以阻止点击事件。

const [isDragging, setIsDragging] = useState(false);
const [startPosition, setStartPosition] = useState({ x: 0, y: 0 });

const handleMouseDown = (e) => {
    setIsDragging(false);
    setStartPosition({ x: e.clientX, y: e.clientY });
};

const handleMouseMove = (e) => {
    const distance = Math.sqrt(
        Math.pow(e.clientX - startPosition.x, 2) + Math.pow(e.clientY - startPosition.y, 2)
    );

    if (distance > 5) {
        setIsDragging(true); // Consider it a drag if the threshold is exceeded
    }
};

const handleMouseUp = () => {
    if (!isDragging) {
        console.log("Div clicked");
    }
};

普鲁巴

<div 
 onMouseDown={handleMouseDown}
 onMouseMove={handleMouseMove}
 onMouseUp={handleMouseUp}  
> Drag or click here </div>
© www.soinside.com 2019 - 2024. All rights reserved.