完整代码
这里介绍 currentDiv 和 useRef的俩中用法,看自己需求使用
import React, {
useState,
DragEvent,
useRef,
useEffect,
MouseEvent,
} from 'react';
interface Demo {
id: number;
x: number;
y: number;
}
const App: React.FC = () => {
const [demos, setDemos] = useState<Demo[]>([]);
// let currentDiv: HTMLDivElement | null = null;
const divRef = useRef<HTMLDivElement | null>(null);
const handleDragStart = (e: DragEvent<HTMLDivElement>, id: number) => {
e.dataTransfer.setData('text/plain', id.toString());
const offsetX = e.clientX - e.currentTarget.getBoundingClientRect().left;
const offsetY = e.clientY - e.currentTarget.getBoundingClientRect().top;
e.dataTransfer.setData('offsetX', offsetX.toString());
e.dataTransfer.setData('offsetY', offsetY.toString());
};
const handleDrop = (e: DragEvent<HTMLDivElement>) => {
e.preventDefault();
const clientX = e.clientX;
const clientY = e.clientY;
const contentStyle = document
.getElementById('content')
.getBoundingClientRect();
const offsetX = e.dataTransfer.getData('offsetX');
const offsetY = e.dataTransfer.getData('offsetY');
const x = clientX - contentStyle.left - offsetX;
const y = clientY - contentStyle.top - offsetY;
const newDemo: Demo = { x, y, id: +new Date() };
setDemos([...demos, newDemo]);
};
const handleDragOver = (e: DragEvent<HTMLDivElement>) => {
e.preventDefault();
};
// const onMouseDown = (e: MouseEvent<HTMLDivElement>) => {
// console.info('onMouseDown', e);
// };
// const onMouseUp = (e: MouseEvent<HTMLDivElement>) => {
// console.info('onMouseUp', e);
// };
const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
// currentDiv = e.currentTarget;
divRef.current = e.currentTarget;
// let { top, left } = currentDiv.style;
// console.info('top, left', top, left);
let { top, left } = divRef.current.style;
console.info('top, left', top, left);
// 如果直接修改属性,值的类型会变为字符串,所以要转为数值型
const startTop = top ? Number(top.replace('px', '')) : 0;
const startLeft = left ? Number(left.replace('px', '')) : 0;
const startY = e.clientY;
const startX = e.clientX;
const move = (moveEvent: { clientX: number; clientY: number }) => {
// if (!currentDiv) return; // 检查currentDiv是否存在
if (!divRef.current) return; // 检查currentDiv是否存在
const currX = moveEvent.clientX;
const currY = moveEvent.clientY;
console.info('move', currX, currY);
top = `${currY - startY + startTop}px`;
left = `${currX - startX + startLeft}px`;
// 修改当前组件样式
// currentDiv.style.left = left;
// currentDiv.style.top = top;
// 修改当前组件样式
divRef.current.style.left = left;
divRef.current.style.top = top;
};
const up = () => {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', up);
// currentDiv = null; // 清除对元素的引用
divRef.current = null;
console.log('removeEventListener');
};
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', up);
};
return (
<div>
<div
id="demo"
draggable
onDragStart={(e) => handleDragStart(e, 1)}
style={{
width: '100px',
height: '100px',
backgroundColor: 'red',
margin: '30px',
cursor: 'pointer',
}}
>
demo2
</div>
<div
id="content"
onDrop={handleDrop}
onDragOver={handleDragOver}
style={{
width: '300px',
height: '300px',
margin: '30px',
backgroundColor: 'blue',
position: 'relative',
}}
>
content
{demos.map((demo) => (
<div
onMouseDown={handleMouseDown}
key={demo.id}
style={{
width: '100px',
height: '100px',
backgroundColor: 'red',
cursor: 'pointer',
position: 'absolute',
left: `${demo.x}px`,
top: `${demo.y}px`,
}}
>
demo {demo.id}
</div>
))}
</div>
</div>
);
};
export default App;