当前位置:首页 > React

react 组件 实现拖拽

2026-01-26 23:24:38React

实现拖拽功能的 React 组件

使用 HTML5 原生拖拽 API

HTML5 提供了原生拖拽 API,可以通过 draggable 属性、onDragStartonDragOveronDrop 等事件实现基础拖拽功能。

import React, { useState } from 'react';

const DragAndDrop = () => {
  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);
  const [draggedItem, setDraggedItem] = useState(null);

  const handleDragStart = (index) => {
    setDraggedItem(items[index]);
  };

  const handleDragOver = (index, e) => {
    e.preventDefault();
    const newItems = [...items];
    const draggedOverItem = newItems[index];

    if (draggedItem === draggedOverItem) return;

    newItems.splice(items.indexOf(draggedItem), 1);
    newItems.splice(index, 0, draggedItem);
    setItems(newItems);
  };

  return (
    <div>
      {items.map((item, index) => (
        <div
          key={item}
          draggable
          onDragStart={() => handleDragStart(index)}
          onDragOver={(e) => handleDragOver(index, e)}
          style={{
            padding: '10px',
            margin: '5px',
            backgroundColor: '#f0f0f0',
            cursor: 'move'
          }}
        >
          {item}
        </div>
      ))}
    </div>
  );
};

export default DragAndDrop;

使用第三方库 react-dnd

对于更复杂的拖拽场景,推荐使用 react-dnd 库,它提供了更强大的功能和更好的性能。

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

const ItemType = 'ITEM';

const DraggableItem = ({ item, index, moveItem }) => {
  const [{ isDragging }, drag] = useDrag({
    type: ItemType,
    item: { index },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });

  const [, drop] = useDrop({
    accept: ItemType,
    hover: (draggedItem) => {
      if (draggedItem.index !== index) {
        moveItem(draggedItem.index, index);
        draggedItem.index = index;
      }
    },
  });

  return (
    <div
      ref={(node) => drag(drop(node))}
      style={{
        opacity: isDragging ? 0.5 : 1,
        padding: '10px',
        margin: '5px',
        backgroundColor: '#f0f0f0',
        cursor: 'move'
      }}
    >
      {item}
    </div>
  );
};

const DragAndDropList = () => {
  const [items, setItems] = React.useState(['Item 1', 'Item 2', 'Item 3']);

  const moveItem = (fromIndex, toIndex) => {
    const newItems = [...items];
    const [removed] = newItems.splice(fromIndex, 1);
    newItems.splice(toIndex, 0, removed);
    setItems(newItems);
  };

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

const App = () => (
  <DndProvider backend={HTML5Backend}>
    <DragAndDropList />
  </DndProvider>
);

export default App;

使用 react-beautiful-dnd 库

react-beautiful-dnd 是另一个流行的拖拽库,特别适合列表重排序场景。

import React, { useState } from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

const DragAndDropList = () => {
  const [items, setItems] = useState([
    { id: '1', content: 'Item 1' },
    { id: '2', content: 'Item 2' },
    { id: '3', content: 'Item 3' },
  ]);

  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}
                    style={{
                      ...provided.draggableProps.style,
                      padding: '10px',
                      margin: '5px',
                      backgroundColor: '#f0f0f0',
                    }}
                  >
                    {item.content}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
};

export default DragAndDropList;

性能优化建议

对于大型列表,应该考虑虚拟化技术(如 react-window)与拖拽库结合使用。react-beautiful-dnd 提供了与 react-window 的集成方案。

所有拖拽操作都应考虑无障碍访问,确保键盘操作可用并为屏幕阅读器提供适当的 ARIA 属性。

react 组件  实现拖拽

标签: 组件拖拽
分享给朋友:

相关文章

vue拖拽实现

vue拖拽实现

Vue 拖拽实现方法 使用 HTML5 原生拖拽 API HTML5 提供了原生拖拽 API,可以通过 draggable 属性、dragstart、dragend、dragover 和 drop 事…

vue拖拽容器实现

vue拖拽容器实现

实现 Vue 拖拽容器的基本方法 使用 HTML5 原生拖拽 API 通过 draggable 属性和拖拽事件(dragstart、dragend、dragover、drop)实现基础拖拽功能。适用于…

vue实现组件封装

vue实现组件封装

Vue 组件封装方法 封装组件的基本步骤 创建独立的 .vue 文件,包含 template、script 和 style 三个部分。通过 props 接收父组件传递的数据,使用 $emit 触发自…

vue实现拖拽

vue实现拖拽

Vue 实现拖拽功能的方法 使用 HTML5 原生拖拽 API HTML5 提供了原生的拖拽 API,可以通过 draggable 属性和相关事件实现拖拽功能。在 Vue 中可以通过绑定这些事件来实现…

vue组件的实现

vue组件的实现

Vue 组件的实现方式 Vue 组件可以通过多种方式实现,主要包括单文件组件(SFC)、全局注册和局部注册。以下是常见的实现方法: 单文件组件(SFC) 单文件组件是 Vue 最推荐的组件化开发方…

vue实现穿梭框树组件

vue实现穿梭框树组件

Vue 穿梭框树组件实现 穿梭框树组件通常结合了树形结构和穿梭框功能,允许用户在左右两栏之间移动树节点数据。以下是基于 Vue 的实现方案: 核心功能设计 数据结构 树形数据通常采用嵌套结构,例如:…