当前位置:首页 > React

react 实现拖拽的组件

2026-01-27 18:05:46React

使用 react-dnd 实现拖拽

react-dnd 是一个流行的 React 拖拽库,基于 HTML5 的拖拽 API 实现。安装 react-dnd 和它的 HTML5 后端依赖:

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

创建一个可拖拽的组件:

import { useDrag } from 'react-dnd';

function 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,
        cursor: 'move',
      }}
    >
      {text}
    </div>
  );
}

创建一个可放置的区域:

import { useDrop } from 'react-dnd';

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

  return (
    <div
      ref={drop}
      style={{
        backgroundColor: isOver ? 'lightblue' : 'white',
        minHeight: '200px',
        border: '1px dashed gray',
      }}
    >
      Drop here
    </div>
  );
}

在应用中使用这些组件:

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

function App() {
  const handleDrop = (id) => {
    console.log(`Dropped item with id: ${id}`);
  };

  return (
    <DndProvider backend={HTML5Backend}>
      <div>
        <DraggableItem id={1} text="Drag me" />
        <DropZone onDrop={handleDrop} />
      </div>
    </DndProvider>
  );
}

使用 react-beautiful-dnd 实现列表拖拽

react-beautiful-dnd 专注于列表的拖拽排序。安装库:

npm install react-beautiful-dnd

实现一个可排序的列表:

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

function SortableList({ items, onReorder }) {
  const handleDragEnd = (result) => {
    if (!result.destination) return;
    onReorder(result.source.index, result.destination.index);
  };

  return (
    <DragDropContext onDragEnd={handleDragEnd}>
      <Droppable droppableId="list">
        {(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: '8px',
                      margin: '4px',
                      backgroundColor: 'white',
                      border: '1px solid lightgray',
                    }}
                  >
                    {item.text}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
}

使用原生 HTML5 拖拽 API

对于简单的需求,可以直接使用 HTML5 的拖拽 API:

function NativeDraggable() {
  const handleDragStart = (e) => {
    e.dataTransfer.setData('text/plain', e.target.id);
  };

  const handleDragOver = (e) => {
    e.preventDefault();
  };

  const handleDrop = (e) => {
    e.preventDefault();
    const id = e.dataTransfer.getData('text/plain');
    const draggedElement = document.getElementById(id);
    e.target.appendChild(draggedElement);
  };

  return (
    <div>
      <div
        id="draggable"
        draggable
        onDragStart={handleDragStart}
        style={{
          padding: '10px',
          backgroundColor: 'lightgray',
          margin: '10px',
          display: 'inline-block',
        }}
      >
        Drag me
      </div>
      <div
        onDragOver={handleDragOver}
        onDrop={handleDrop}
        style={{
          width: '200px',
          height: '200px',
          border: '1px dashed black',
          padding: '10px',
        }}
      >
        Drop here
      </div>
    </div>
  );
}

性能优化建议

对于大型列表,使用 react-window 或 react-virtualized 来虚拟化渲染:

import { FixedSizeList } from 'react-window';
import { Droppable, Draggable } from 'react-beautiful-dnd';

function VirtualizedList({ items }) {
  const Row = ({ index, style }) => (
    <Draggable draggableId={items[index].id} index={index}>
      {(provided) => (
        <div
          ref={provided.innerRef}
          {...provided.draggableProps}
          {...provided.dragHandleProps}
          style={{
            ...provided.draggableProps.style,
            ...style,
          }}
        >
          {items[index].text}
        </div>
      )}
    </Draggable>
  );

  return (
    <DragDropContext onDragEnd={handleDragEnd}>
      <Droppable droppableId="list">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            <FixedSizeList
              height={500}
              itemCount={items.length}
              itemSize={50}
              width={300}
            >
              {Row}
            </FixedSizeList>
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
}

react 实现拖拽的组件

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

相关文章

前端实现拖拽功能vue

前端实现拖拽功能vue

实现拖拽功能的基本方法 在Vue中实现拖拽功能可以通过HTML5的拖放API或第三方库如vuedraggable来完成。HTML5的拖放API提供了原生支持,而vuedraggable则简化了列表拖拽…

js实现拖拽

js实现拖拽

实现拖拽的基本步骤 使用JavaScript实现拖拽功能需要监听鼠标事件,包括mousedown、mousemove和mouseup。以下是实现的基本逻辑: const draggableEleme…

vue实现组件封装

vue实现组件封装

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

vue 中实现拖拽

vue 中实现拖拽

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

vue实现水印组件

vue实现水印组件

Vue 水印组件实现 基础水印组件实现 创建一个基础水印组件,通过 props 接收文本、颜色、大小等参数: <template> <div class="watermark…

vue组件的实现

vue组件的实现

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