完整代码
这里介绍 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><divid="demo"draggableonDragStart={(e) => handleDragStart(e, 1)}style={{width: '100px',height: '100px',backgroundColor: 'red',margin: '30px',cursor: 'pointer',}}>demo2</div><divid="content"onDrop={handleDrop}onDragOver={handleDragOver}style={{width: '300px',height: '300px',margin: '30px',backgroundColor: 'blue',position: 'relative',}}>content{demos.map((demo) => (<divonMouseDown={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;