当前位置:首页 > React

react实现组合拖拽

2026-01-27 05:13:14React

React 实现组合拖拽

在 React 中实现组合拖拽功能可以通过多种方式完成,常见的方法是使用第三方库如 react-dndreact-beautiful-dnd。以下是两种主要实现方式:

使用 react-dnd

react-dnd 是一个基于 HTML5 拖拽 API 的 React 拖拽库,适合复杂的拖拽场景。

安装依赖:

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

基本实现:

react实现组合拖拽

import { useDrag, useDrop, DndProvider } 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',
        border: '1px solid #ccc',
      }}
    >
      {text}
    </div>
  );
};

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

  return (
    <div
      ref={drop}
      style={{
        background: isOver ? '#f0f0f0' : '#fff',
        padding: '16px',
        border: '2px dashed #999',
      }}
    >
      Drop here
    </div>
  );
};

const App = () => {
  const handleDrop = (id) => {
    console.log(`Item ${id} dropped`);
  };

  return (
    <DndProvider backend={HTML5Backend}>
      <div style={{ display: 'flex' }}>
        <div>
          <DraggableItem id="1" text="Item 1" />
          <DraggableItem id="2" text="Item 2" />
        </div>
        <DropZone onDrop={handleDrop} />
      </div>
    </DndProvider>
  );
};

使用 react-beautiful-dnd

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

安装依赖:

react实现组合拖拽

npm install react-beautiful-dnd

基本实现:

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

const items = [
  { id: '1', text: 'Item 1' },
  { id: '2', text: 'Item 2' },
];

const App = () => {
  const [state, setState] = useState(items);

  const onDragEnd = (result) => {
    if (!result.destination) return;

    const newItems = Array.from(state);
    const [removed] = newItems.splice(result.source.index, 1);
    newItems.splice(result.destination.index, 0, removed);

    setState(newItems);
  };

  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable droppableId="droppable">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {state.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                    style={{
                      padding: '8px',
                      margin: '4px',
                      border: '1px solid #ccc',
                      ...provided.draggableProps.style,
                    }}
                  >
                    {item.text}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
};

自定义实现

如果需要更轻量级的解决方案,可以直接使用 HTML5 拖拽 API:

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

  return (
    <div
      draggable
      onDragStart={handleDragStart}
      style={{ padding: '8px', margin: '4px', border: '1px solid #ccc' }}
    >
      {text}
    </div>
  );
};

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

  const handleDrop = (e) => {
    e.preventDefault();
    const id = e.dataTransfer.getData('text/plain');
    onDrop(id);
  };

  return (
    <div
      onDragOver={handleDragOver}
      onDrop={handleDrop}
      style={{ padding: '16px', border: '2px dashed #999' }}
    >
      Drop here
    </div>
  );
};

性能优化

对于大量拖拽项,使用 react-windowreact-virtualized 进行虚拟滚动可以提升性能。

import { FixedSizeList } from 'react-window';

const Row = ({ data, index, style }) => (
  <Draggable
    id={data[index].id}
    text={data[index].text}
    style={style}
  />
);

const VirtualizedList = ({ items }) => (
  <FixedSizeList
    height={400}
    width={300}
    itemCount={items.length}
    itemSize={50}
    itemData={items}
  >
    {Row}
  </FixedSizeList>
);

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

相关文章

vue实现组合查询

vue实现组合查询

vue实现组合查询 组合查询通常涉及多个条件的联合筛选,Vue可以结合计算属性、v-model和数组方法实现高效查询。以下是具体实现方式: 数据准备与绑定 在Vue组件中定义查询条件和数据集合:…

vue实现模块拖拽

vue实现模块拖拽

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

前端实现拖拽功能vue

前端实现拖拽功能vue

使用 HTML5 拖放 API 在 Vue 中可以通过 HTML5 的原生拖放 API 实现拖拽功能。需要监听 dragstart、dragover 和 drop 事件。 <template…

vue 实现拖拽甘特图

vue 实现拖拽甘特图

实现拖拽甘特图的核心思路 Vue 实现拖拽甘特图需要结合第三方库或自定义逻辑,核心功能包括任务条渲染、时间轴刻度、拖拽交互、数据绑定等。以下是具体实现方法: 使用第三方库(推荐) vue-gantt…

vue实现组合查询

vue实现组合查询

Vue 实现组合查询 组合查询通常指用户通过多个条件筛选数据,Vue 可以通过数据绑定、计算属性和方法实现这一功能。以下是具体实现方式: 数据绑定与表单设计 在 Vue 组件的 data 中定义查询…

vue实现拖拽放置

vue实现拖拽放置

Vue 实现拖拽放置功能 拖拽放置功能可以通过 Vue 的指令或第三方库实现。以下是两种常见的方法: 使用 HTML5 原生拖拽 API HTML5 提供了原生的拖拽 API,可以通过 dragga…