当前位置:首页 > React

react 实现拖拽

2026-01-26 10:39:15React

实现拖拽的基本步骤

安装依赖库react-dndreact-dnd-html5-backend

npm install react-dnd react-dnd-html5-backend

引入必要模块:

import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';

创建可拖拽组件

定义拖拽源组件:

react 实现拖拽

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,
        padding: '8px',
        margin: '4px',
        backgroundColor: '#f0f0f0',
        cursor: 'move',
      }}
    >
      {text}
    </div>
  );
};

创建放置目标组件

定义放置目标组件:

const DropZone = ({ onDrop }) => {
  const [{ canDrop, isOver }, drop] = useDrop(() => ({
    accept: 'ITEM',
    drop: (item) => onDrop(item.id),
    collect: (monitor) => ({
      isOver: !!monitor.isOver(),
      canDrop: !!monitor.canDrop(),
    }),
  }));

  const backgroundColor = canDrop ? (isOver ? '#d4edda' : '#f8f9fa') : '#ffffff';

  return (
    <div
      ref={drop}
      style={{
        padding: '16px',
        margin: '8px',
        border: '2px dashed #ccc',
        backgroundColor,
      }}
    >
      {canDrop ? '释放放置' : '拖拽到此区域'}
    </div>
  );
};

组合组件实现完整功能

实现完整的拖拽交互:

react 实现拖拽

const App = () => {
  const [items, setItems] = useState([
    { id: 1, text: '项目1' },
    { id: 2, text: '项目2' },
    { id: 3, text: '项目3' },
  ]);

  const [droppedItems, setDroppedItems] = useState([]);

  const handleDrop = (id) => {
    const item = items.find((i) => i.id === id);
    setDroppedItems([...droppedItems, item]);
    setItems(items.filter((i) => i.id !== id));
  };

  return (
    <DndProvider backend={HTML5Backend}>
      <div style={{ display: 'flex' }}>
        <div style={{ width: '200px' }}>
          {items.map((item) => (
            <DraggableItem key={item.id} id={item.id} text={item.text} />
          ))}
        </div>
        <DropZone onDrop={handleDrop} />
        <div>
          {droppedItems.map((item) => (
            <div key={item.id}>{item.text}</div>
          ))}
        </div>
      </div>
    </DndProvider>
  );
};

自定义拖拽预览

实现自定义拖拽预览效果:

const CustomDragPreview = ({ item }) => {
  return (
    <div
      style={{
        backgroundColor: '#007bff',
        color: 'white',
        padding: '8px',
        borderRadius: '4px',
        boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
      }}
    >
      {item.text}
    </div>
  );
};

// 在useDrag配置中添加preview选项
const [{ isDragging }, drag, preview] = useDrag(() => ({
  type: 'ITEM',
  item: { id, text },
}));

return (
  <>
    <div ref={preview} style={{ display: 'none' }} />
    <div ref={drag}>{text}</div>
  </>
);

处理复杂数据类型

处理复杂数据类型的拖拽:

const handleDrop = (item) => {
  if (item.type === 'TASK') {
    // 处理任务数据
  } else if (item.type === 'FILE') {
    // 处理文件数据
  }
};

// 在useDrop中配置多种accept类型
useDrop(() => ({
  accept: ['TASK', 'FILE'],
  drop: handleDrop,
}));

实现排序功能

实现列表内拖拽排序:

const SortableList = ({ items, onMove }) => {
  const moveItem = (dragIndex, hoverIndex) => {
    const dragItem = items[dragIndex];
    const newItems = [...items];
    newItems.splice(dragIndex, 1);
    newItems.splice(hoverIndex, 0, dragItem);
    onMove(newItems);
  };

  return (
    <div>
      {items.map((item, index) => (
        <SortableItem
          key={item.id}
          index={index}
          item={item}
          moveItem={moveItem}
        />
      ))}
    </div>
  );
};

const SortableItem = ({ index, item, moveItem }) => {
  const ref = useRef(null);
  const [{ isDragging }, drag] = useDrag({
    type: 'ITEM',
    item: { index },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });

  const [, drop] = useDrop({
    accept: 'ITEM',
    hover: (draggedItem, monitor) => {
      if (draggedItem.index === index) return;
      moveItem(draggedItem.index, index);
      draggedItem.index = index;
    },
  });

  drag(drop(ref));

  return (
    <div
      ref={ref}
      style={{
        opacity: isDragging ? 0.5 : 1,
        padding: '8px',
        margin: '4px',
        backgroundColor: '#f0f0f0',
        cursor: 'move',
      }}
    >
      {item.text}
    </div>
  );
};

标签: 拖拽react
分享给朋友:

相关文章

react如何取消渲染

react如何取消渲染

取消渲染的方法 在React中,取消渲染通常指阻止组件在特定条件下进行不必要的渲染。可以通过以下几种方式实现: 条件渲染 使用条件语句(如if或三元运算符)直接返回null,避免渲染组件内容。例如:…

react 如何执行

react 如何执行

安装 Node.js 和 npm React 开发需要 Node.js 环境,因为它提供了 npm(或 yarn)包管理工具。从 Node.js 官网 下载并安装最新 LTS 版本。安装完成后,在终端…

react如何取消渲染

react如何取消渲染

取消渲染的方法 在React中,取消渲染通常指的是在某些条件下阻止组件渲染或中断正在进行的渲染过程。以下是几种常见的方法: 条件渲染 通过条件判断决定是否渲染组件或部分内容。可以使用if语句或三元运…

vue拖拽实现

vue拖拽实现

vue拖拽实现方法 使用HTML5原生拖拽API HTML5提供原生拖拽API,通过draggable属性、dragstart、dragend等事件实现基础拖拽功能。 <template>…

react如何开发组件

react如何开发组件

React 组件开发基础 React 组件分为函数组件和类组件两种形式。函数组件是现代 React 开发的主流方式,结合 Hooks 可以实现完整功能。 函数组件示例: function Gree…

vue实现拖拽div

vue实现拖拽div

实现拖拽功能的基本思路 在Vue中实现拖拽功能可以通过HTML5的拖拽API或第三方库如vuedraggable来完成。以下是两种常见方法的详细说明: 使用HTML5拖拽API HTML5提供了原生…