当前位置:首页 > React

react实现组件拖拽

2026-01-27 08:45:05React

实现拖拽功能的基本方法

使用HTML5的拖放API结合React状态管理实现基础拖拽。需要监听dragstartdragenddragoverdrop事件。

import { useState } from 'react';

function DraggableComponent() {
  const [isDragging, setIsDragging] = useState(false);

  const handleDragStart = (e) => {
    e.dataTransfer.setData('text/plain', 'drag-data');
    setIsDragging(true);
  };

  const handleDragEnd = () => {
    setIsDragging(false);
  };

  return (
    <div
      draggable
      onDragStart={handleDragStart}
      onDragEnd={handleDragEnd}
      style={{
        opacity: isDragging ? 0.5 : 1,
        cursor: 'move'
      }}
    >
      Drag me
    </div>
  );
}

实现拖放目标区域

创建可放置区域需要处理dragoverdrop事件,阻止默认行为是关键。

function DropZone() {
  const [hasDropped, setHasDropped] = useState(false);

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

  const handleDrop = (e) => {
    e.preventDefault();
    const data = e.dataTransfer.getData('text/plain');
    console.log('Dropped data:', data);
    setHasDropped(true);
  };

  return (
    <div
      onDragOver={handleDragOver}
      onDrop={handleDrop}
      style={{
        width: '200px',
        height: '200px',
        border: '2px dashed gray',
        backgroundColor: hasDropped ? 'lightgreen' : 'white'
      }}
    >
      Drop here
    </div>
  );
}

使用第三方库react-dnd

对于复杂拖拽场景,推荐使用react-dnd库。安装命令:npm install react-dnd react-dnd-html5-backend

import { useDrag, useDrop } from 'react-dnd';

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

function DropContainer({ children }) {
  const [, drop] = useDrop({
    accept: 'ITEM',
    drop: (item, monitor) => {
      console.log('Dropped item:', item);
    }
  });

  return (
    <div
      ref={drop}
      style={{
        width: '300px',
        minHeight: '200px',
        border: '2px solid gray',
        padding: '16px'
      }}
    >
      {children}
    </div>
  );
}

实现列表排序拖拽

结合react-dnd实现可排序列表需要处理hover状态和位置交换。

function SortableList({ items, onMove }) {
  return (
    <DropContainer>
      {items.map((item, index) => (
        <SortableItem 
          key={item.id}
          index={index}
          item={item}
          onMove={onMove}
        />
      ))}
    </DropContainer>
  );
}

function SortableItem({ item, index, onMove }) {
  const [, drop] = useDrop({
    accept: 'ITEM',
    hover(draggedItem) {
      if (draggedItem.index !== index) {
        onMove(draggedItem.index, index);
        draggedItem.index = index;
      }
    }
  });

  const [{ isDragging }, drag] = useDrag({
    type: 'ITEM',
    item: { ...item, index },
    collect: (monitor) => ({
      isDragging: !!monitor.isDragging()
    })
  });

  return (
    <div
      ref={(node) => drag(drop(node))}
      style={{
        opacity: isDragging ? 0.5 : 1,
        padding: '8px',
        margin: '4px',
        backgroundColor: 'lightblue',
        cursor: 'move'
      }}
    >
      {item.text}
    </div>
  );
}

性能优化建议

对于大型列表实现拖拽时,考虑使用react-window或react-virtualized进行虚拟滚动。避免在拖拽过程中频繁重渲染整个列表。

自定义拖拽预览可以通过useDragpreview选项实现,或者使用HTML5的setDragImage方法。

react实现组件拖拽

const [, drag, preview] = useDrag({
  type: 'ITEM',
  item: { id }
});

useEffect(() => {
  const img = new Image();
  img.src = 'preview.png';
  preview(img);
}, [preview]);

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

相关文章

vue实现广告组件

vue实现广告组件

vue实现广告组件的方法 使用动态组件实现 在Vue中可以通过动态组件的方式加载广告组件,根据不同的条件展示不同的广告内容。动态组件使用<component :is="currentCompon…

uniapp 分页组件

uniapp 分页组件

uniapp 分页组件实现方法 在uniapp中实现分页功能,可以通过自定义组件或使用第三方组件库完成。以下是几种常见实现方式: 自定义分页组件 创建一个名为uni-pagination的组件,模板…

vue 组件实现 遮罩

vue 组件实现 遮罩

Vue 组件实现遮罩层的方法 基础遮罩层实现 创建一个简单的遮罩层组件,使用绝对定位覆盖整个视口。以下是一个基础实现: <template> <div class="mask"…

vue实现秒表组件

vue实现秒表组件

实现秒表组件的基本思路 使用Vue实现秒表组件需要管理时间状态、控制计时器的启动/暂停/重置功能,并通过计算属性动态显示格式化时间。核心逻辑包括利用setInterval更新计时数据,并通过生命周期钩…

利用vue实现拖拽

利用vue实现拖拽

使用 Vue 实现拖拽功能 原生 HTML5 拖拽 API Vue 可以结合 HTML5 的拖拽 API 实现基础拖拽功能。以下是一个简单示例: <template> <div…

vue实现search组件

vue实现search组件

Vue 实现搜索组件 基础实现 创建一个基础的搜索组件需要包含输入框和搜索逻辑。以下是一个简单的实现示例: <template> <div class="search-cont…