使用 onMouseMove() 时,ReactJS 中的自定义、可拖动组件太慢
Custom, Draggable component too slow in ReactJS when Using onMouseMove()
我正在尝试创建一个可拖动的 preact 组件。如果光标快速移动,我当前的实现就会中断。这是代码。
export { Draggable };
import { h } from "preact";
import { useState } from "preact/hooks";
const Draggable = (props: any) => {
const [styles, setStyles] = useState({});
const [diffPos, setDiffPos] = useState({ diffX: 0, diffY: 0 });
const [isDragging, setIsDragging] = useState(false);
const dragStart = (e: MouseEvent): void => {
const boundingRect =
(e.currentTarget as HTMLElement).getBoundingClientRect();
setDiffPos({
diffX: e.screenX - boundingRect.left,
diffY: e.screenY - boundingRect.top,
});
setIsDragging(true);
}
const dragging = (e: MouseEvent): void => {
if (isDragging === true) {
const left = e.screenX - diffPos.diffX;
const top = e.screenY - diffPos.diffY;
setStyles({ left: left, top: top });
}
}
const dragEnd = (): void => {
setIsDragging(false);
}
return (
<div
class="draggable"
style={{ ...styles, position: "absolute" }}
onMouseDown={dragStart}
onMouseMove={dragging}
onMouseUp={dragEnd}
>
{props.children}
</div>
);
}
我试图通过创建一个 mouseup
事件侦听器来修复它,但是如果我将鼠标移动到快速,元素就会停止拖动。
这是我尝试的修复方法:
export { Draggable };
import { h } from "preact";
import { useState } from "preact/hooks";
const Draggable = (props: any) => {
const [styles, setStyles] = useState({});
const [diffPos, setDiffPos] = useState({ diffX: 0, diffY: 0 });
const [isDragging, setIsDragging] = useState(false);
const dragStart = (e: MouseEvent): void => {
const boundingRect =
(e.currentTarget as HTMLElement).getBoundingClientRect();
setDiffPos({
diffX: e.screenX - boundingRect.left,
diffY: e.screenY - boundingRect.top,
});
setIsDragging(true);
// ------------------------------------------------------------ Added an event listener
document.addEventListener("mouseup", dragEnd, { once: true });
}
const dragging = (e: MouseEvent): void => {
if (isDragging === true) {
const left = e.screenX - diffPos.diffX;
const top = e.screenY - diffPos.diffY;
setStyles({ left: left, top: top });
}
}
const dragEnd = (): void => {
setIsDragging(false);
}
return (
<div
class="draggable"
style={{ ...styles, position: "absolute" }}
onMouseDown={dragStart}
onMouseMove={dragging}
// -------------------------------------------------------- Removed onMouseUp
>
{props.children}
</div>
);
}
问题是每次移动鼠标时 onMouseMove()
都会触发,因此,如果您非常缓慢地移动超过 200 个像素,那就是 200 次迭代。尝试使用 onDragStart
和 onDragEnd
。 Full working demo.
最终,您的更改将在 render()
...
return (
<div
class="draggable"
style={{ ...styles, position: "absolute" }}
onDragStart={(e) => dragStart(e)}
onDragEnd={(e) => dragging(e)}
draggable={true}
>
{props.children}
</div>
);
我使用 dragEnd()
,所以实际上只有两个事件会随着拖动而触发:开始和结束。每次移动时都会触发 MouseMove,在拖动过程中可能会触发数百次。
此外,通过给它额外的 draggable={true}
参数,浏览器会将其视为 naturally-draggable 项目(即,拖动项目的 semi-opaque 版本将在视觉上显示在光标的位置,当用户拖动元素时)。
最后,为了稍微加快速度,我删除了 eventListener
你在 dragStart()
中为 dragEnd
设置的 eventListener
。
我正在尝试创建一个可拖动的 preact 组件。如果光标快速移动,我当前的实现就会中断。这是代码。
export { Draggable };
import { h } from "preact";
import { useState } from "preact/hooks";
const Draggable = (props: any) => {
const [styles, setStyles] = useState({});
const [diffPos, setDiffPos] = useState({ diffX: 0, diffY: 0 });
const [isDragging, setIsDragging] = useState(false);
const dragStart = (e: MouseEvent): void => {
const boundingRect =
(e.currentTarget as HTMLElement).getBoundingClientRect();
setDiffPos({
diffX: e.screenX - boundingRect.left,
diffY: e.screenY - boundingRect.top,
});
setIsDragging(true);
}
const dragging = (e: MouseEvent): void => {
if (isDragging === true) {
const left = e.screenX - diffPos.diffX;
const top = e.screenY - diffPos.diffY;
setStyles({ left: left, top: top });
}
}
const dragEnd = (): void => {
setIsDragging(false);
}
return (
<div
class="draggable"
style={{ ...styles, position: "absolute" }}
onMouseDown={dragStart}
onMouseMove={dragging}
onMouseUp={dragEnd}
>
{props.children}
</div>
);
}
我试图通过创建一个 mouseup
事件侦听器来修复它,但是如果我将鼠标移动到快速,元素就会停止拖动。
这是我尝试的修复方法:
export { Draggable };
import { h } from "preact";
import { useState } from "preact/hooks";
const Draggable = (props: any) => {
const [styles, setStyles] = useState({});
const [diffPos, setDiffPos] = useState({ diffX: 0, diffY: 0 });
const [isDragging, setIsDragging] = useState(false);
const dragStart = (e: MouseEvent): void => {
const boundingRect =
(e.currentTarget as HTMLElement).getBoundingClientRect();
setDiffPos({
diffX: e.screenX - boundingRect.left,
diffY: e.screenY - boundingRect.top,
});
setIsDragging(true);
// ------------------------------------------------------------ Added an event listener
document.addEventListener("mouseup", dragEnd, { once: true });
}
const dragging = (e: MouseEvent): void => {
if (isDragging === true) {
const left = e.screenX - diffPos.diffX;
const top = e.screenY - diffPos.diffY;
setStyles({ left: left, top: top });
}
}
const dragEnd = (): void => {
setIsDragging(false);
}
return (
<div
class="draggable"
style={{ ...styles, position: "absolute" }}
onMouseDown={dragStart}
onMouseMove={dragging}
// -------------------------------------------------------- Removed onMouseUp
>
{props.children}
</div>
);
}
问题是每次移动鼠标时 onMouseMove()
都会触发,因此,如果您非常缓慢地移动超过 200 个像素,那就是 200 次迭代。尝试使用 onDragStart
和 onDragEnd
。 Full working demo.
最终,您的更改将在 render()
...
return (
<div
class="draggable"
style={{ ...styles, position: "absolute" }}
onDragStart={(e) => dragStart(e)}
onDragEnd={(e) => dragging(e)}
draggable={true}
>
{props.children}
</div>
);
我使用 dragEnd()
,所以实际上只有两个事件会随着拖动而触发:开始和结束。每次移动时都会触发 MouseMove,在拖动过程中可能会触发数百次。
此外,通过给它额外的 draggable={true}
参数,浏览器会将其视为 naturally-draggable 项目(即,拖动项目的 semi-opaque 版本将在视觉上显示在光标的位置,当用户拖动元素时)。
最后,为了稍微加快速度,我删除了 eventListener
你在 dragStart()
中为 dragEnd
设置的 eventListener
。