react实现拖拽按钮
React 实现拖拽按钮的方法
使用 HTML5 拖放 API
HTML5 提供了原生的拖放 API,可以直接在 React 中使用。通过 draggable 属性、onDragStart、onDragOver 和 onDrop 等事件实现拖拽功能。
import React, { useState } from 'react';
const DraggableButton = () => {
const [position, setPosition] = useState({ x: 0, y: 0 });
const handleDragStart = (e) => {
e.dataTransfer.setData('text/plain', 'draggable-button');
};
const handleDragOver = (e) => {
e.preventDefault();
};
const handleDrop = (e) => {
e.preventDefault();
setPosition({
x: e.clientX,
y: e.clientY,
});
};
return (
<div
onDragOver={handleDragOver}
onDrop={handleDrop}
style={{ width: '100%', height: '500px', border: '1px solid #ccc' }}
>
<button
draggable
onDragStart={handleDragStart}
style={{
position: 'absolute',
left: `${position.x}px`,
top: `${position.y}px`,
cursor: 'move',
}}
>
Drag Me
</button>
</div>
);
};
export default DraggableButton;
使用第三方库 react-dnd
react-dnd 是一个流行的拖拽库,提供了更灵活的拖拽功能,适合复杂场景。
安装依赖:

npm install react-dnd react-dnd-html5-backend
实现代码:
import React from 'react';
import { useDrag, useDrop, DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
const ItemTypes = {
BUTTON: 'button',
};
const DraggableButton = () => {
const [{ isDragging }, drag] = useDrag(() => ({
type: ItemTypes.BUTTON,
collect: (monitor) => ({
isDragging: !!monitor.isDragging(),
}),
}));
return (
<button
ref={drag}
style={{
opacity: isDragging ? 0.5 : 1,
cursor: 'move',
}}
>
Drag Me
</button>
);
};
const DropArea = () => {
const [{ canDrop, isOver }, drop] = useDrop(() => ({
accept: ItemTypes.BUTTON,
drop: () => ({ name: 'DropArea' }),
collect: (monitor) => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
}),
}));
const isActive = canDrop && isOver;
let backgroundColor = '#fff';
if (isActive) backgroundColor = '#ddd';
else if (canDrop) backgroundColor = '#eee';
return (
<div
ref={drop}
style={{
width: '100%',
height: '500px',
border: '1px solid #ccc',
backgroundColor,
}}
>
{isActive ? 'Release to drop' : 'Drag button here'}
</div>
);
};
const App = () => {
return (
<DndProvider backend={HTML5Backend}>
<div>
<DraggableButton />
<DropArea />
</div>
</DndProvider>
);
};
export default App;
使用 react-beautiful-dnd
react-beautiful-dnd 是另一个强大的拖拽库,适合列表和网格中的拖拽排序。

安装依赖:
npm install react-beautiful-dnd
实现代码:
import React from 'react';
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
const items = [
{ id: '1', content: 'Button 1' },
{ id: '2', content: 'Button 2' },
{ id: '3', content: 'Button 3' },
];
const DraggableButtons = () => {
const [buttons, setButtons] = React.useState(items);
const handleDragEnd = (result) => {
if (!result.destination) return;
const newButtons = Array.from(buttons);
const [reorderedItem] = newButtons.splice(result.source.index, 1);
newButtons.splice(result.destination.index, 0, reorderedItem);
setButtons(newButtons);
};
return (
<DragDropContext onDragEnd={handleDragEnd}>
<Droppable droppableId="buttons">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{buttons.map(({ id, content }, index) => (
<Draggable key={id} draggableId={id} index={index}>
{(provided) => (
<button
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
...provided.draggableProps.style,
margin: '8px',
padding: '8px',
cursor: 'move',
}}
>
{content}
</button>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
};
export default DraggableButtons;
自定义拖拽实现
如果需要更简单的自定义拖拽,可以通过鼠标事件实现。
import React, { useState, useRef } from 'react';
const CustomDraggableButton = () => {
const [position, setPosition] = useState({ x: 0, y: 0 });
const [isDragging, setIsDragging] = useState(false);
const buttonRef = useRef(null);
const handleMouseDown = (e) => {
setIsDragging(true);
const rect = buttonRef.current.getBoundingClientRect();
const offsetX = e.clientX - rect.left;
const offsetY = e.clientY - rect.top;
const handleMouseMove = (e) => {
if (!isDragging) return;
setPosition({
x: e.clientX - offsetX,
y: e.clientY - offsetY,
});
};
const handleMouseUp = () => {
setIsDragging(false);
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
};
return (
<div style={{ width: '100%', height: '500px', border: '1px solid #ccc' }}>
<button
ref={buttonRef}
onMouseDown={handleMouseDown}
style={{
position: 'absolute',
left: `${position.x}px`,
top: `${position.y}px`,
cursor: isDragging ? 'grabbing' : 'grab',
}}
>
Drag Me
</button>
</div>
);
};
export default CustomDraggableButton;
以上方法可以根据需求选择,HTML5 拖放 API 适合简单场景,第三方库适合复杂交互,自定义实现则提供了最大的灵活性。






