react实现组件拖动
React 实现组件拖动的方法
使用 react-dnd 库
react-dnd 是一个流行的拖放库,适合复杂场景。安装命令:
npm install react-dnd react-dnd-html5-backend
基础实现示例:
import { useDrag, useDrop } from 'react-dnd';
const DraggableItem = ({ id, text }) => {
const [{ isDragging }, drag] = useDrag(() => ({
type: 'ITEM',
item: { id },
collect: (monitor) => ({
isDragging: !!monitor.isDragging(),
}),
}));
return (
<div ref={drag} style={{ opacity: isDragging ? 0.5 : 1 }}>
{text}
</div>
);
};
const DropZone = ({ onDrop }) => {
const [{ isOver }, drop] = useDrop(() => ({
accept: 'ITEM',
drop: (item) => onDrop(item.id),
collect: (monitor) => ({
isOver: !!monitor.isOver(),
}),
}));
return <div ref={drop} style={{ background: isOver ? 'lightgray' : 'white' }} />;
};
使用 react-beautiful-dnd 库
适合列表重排序场景,安装命令:
npm install react-beautiful-dnd
垂直列表拖动示例:
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
function App() {
const [items, setItems] = useState([...]);
const onDragEnd = (result) => {
if (!result.destination) return;
const newItems = Array.from(items);
const [removed] = newItems.splice(result.source.index, 1);
newItems.splice(result.destination.index, 0, removed);
setItems(newItems);
};
return (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="droppable">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{items.map((item, index) => (
<Draggable key={item.id} draggableId={item.id} index={index}>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
{item.content}
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}
原生实现方案
通过 HTML5 Drag and Drop API 结合 React 状态管理实现:
function DraggableComponent() {
const [position, setPosition] = useState({ x: 0, y: 0 });
const [isDragging, setIsDragging] = useState(false);
const handleDragStart = (e) => {
setIsDragging(true);
e.dataTransfer.setData('text/plain', '');
};
const handleDragEnd = (e) => {
setIsDragging(false);
setPosition({
x: e.clientX,
y: e.clientY
});
};
return (
<div
draggable
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
style={{
position: 'absolute',
left: position.x,
top: position.y,
opacity: isDragging ? 0.5 : 1
}}
>
可拖动元素
</div>
);
}
性能优化建议
对于大量可拖动项目,使用 react-window 或 react-virtualized 进行虚拟滚动。动态加载的列表应实现占位符和延迟渲染。
移动端适配需注意 touch 事件处理,部分库可能需要额外 polyfill。自定义拖动预览可通过 dragLayer 或 setDragImage 实现。






