当前位置:首页 > 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';

创建可拖拽组件

定义拖拽源组件:

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>
  );
};

组合组件实现完整功能

实现完整的拖拽交互:

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

卸载 React 项目依赖 打开项目根目录下的 package.json 文件,删除所有包含 react、react-dom 或其他 React 相关库的依赖项。保存文件后运行以下命令: npm…

react native 如何

react native 如何

React Native 开发基础 React Native 是一个用于构建跨平台移动应用的框架,允许开发者使用 JavaScript 和 React 编写代码,同时生成原生 iOS 和 Androi…

react中monent如何获取日期

react中monent如何获取日期

使用 Moment.js 获取当前日期 在 React 中通过 Moment.js 获取当前日期,可以直接调用 moment() 函数。它会返回包含当前日期和时间的 Moment 对象。 impo…

react moment如何使用

react moment如何使用

安装 react-moment 通过 npm 或 yarn 安装 react-moment: npm install react-moment 或 yarn add react-moment…

js实现拖拽

js实现拖拽

实现拖拽的基本步骤 通过监听鼠标事件(mousedown、mousemove、mouseup)实现拖拽功能。以下是核心代码逻辑: const draggableElement = document.…

react如何开发组件

react如何开发组件

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