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

基本实现:

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 是另一个流行的拖拽库,适合列表重排序等场景。

安装依赖:

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 进行虚拟滚动可以提升性能。

react实现组合拖拽

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拖拽实现方式 使用HTML5原生拖拽API HTML5提供了原生的拖拽API,可以通过draggable属性、dragstart、dragend、dragover和drop等事件实现基础拖拽功能…

vue内实现拖拽

vue内实现拖拽

Vue 实现拖拽功能的方法 使用 HTML5 原生拖拽 API HTML5 提供了原生的拖拽 API,可以通过 draggable 属性和相关事件实现拖拽功能。 <template>…

vue实现盒子拖拽

vue实现盒子拖拽

实现盒子拖拽的基本思路 在Vue中实现盒子拖拽功能,可以通过监听鼠标事件(mousedown、mousemove、mouseup)来实现。核心逻辑是记录拖拽起始位置,计算位移差值,并更新盒子的位置。…

vue 实现拖拽功能

vue 实现拖拽功能

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

vue实现拖拽图层

vue实现拖拽图层

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

vue实现拖拽旋转

vue实现拖拽旋转

Vue 实现拖拽旋转 核心思路 通过监听鼠标事件计算旋转角度,结合 CSS 的 transform: rotate() 实现旋转效果。需要处理 mousedown、mousemove 和 mouseu…