使用React、Js、Mui实现拖拽功能

使用React、Js、Mui实现拖拽功能

能够左右拖拽,并且右侧可以拖拽排序

使用到的库@dnd-kit/core、@dnd-kit/sortable、'@dnd-kit/utilities

安装

npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities

主页面DragContainer

import React, { useState } from 'react';
import { Stack, Box } from '@mui/material';

import LeftArea from './leftArea';
import RightArea from './rightArea';

const DragContainer = () => {
  const [leftItems, setLeftItems] = useState([
    { id: '1', name: 'Item 1' },
    { id: '2', name: 'Item 2' },
    { id: '3', name: 'Item 3' },
    { id: '4', name: 'Item 4' },
    { id: '5', name: 'Item 5' },
    { id: '6', name: 'Item 6' },
    { id: '7', name: 'Item 7' },
    { id: '8', name: 'Item 8' },
    { id: '9', name: 'Item 9' },
    { id: '10', name: 'Item 10' },
    { id: '11', name: 'Item 11' },
    { id: '12', name: 'Item 12' },
  ]);
  const [rightItems, setRightItems] = useState([]);

  const handleDragStart = (e, item) => {
    e.dataTransfer.setData('application/json', JSON.stringify(item));
  };

  const handleDrop = (e) => {
    const data = e.dataTransfer.getData('application/json');
    const item = JSON.parse(data);

    setRightItems((prev) => [...prev, item]);
    // setLeftItems((prev) => prev.filter((i) => i.id !== item.id));
  };

  const disabledItems = rightItems.map((item) => item.id);
  return (
    <Stack direction="row" spacing={2}>
      <LeftArea
        items={leftItems}
        onDragStart={handleDragStart}
        disabledItems={disabledItems}
      />
      <Box
        style={{ flex: 1 }}
        onDragOver={(e) => e.preventDefault()}
        onDrop={handleDrop}
      >
        <RightArea items={rightItems} setItems={setRightItems} />
      </Box>
    </Stack>
  );
};

export default DragContainer;

左侧区域LeftArea

import React from 'react';

import { Paper, Stack, Typography } from '@mui/material';

const LeftArea = ({ items, onDragStart, disabledItems }) => {
  return (
    <Paper
      elevation={3}
      style={{
        padding: '16px',
        minWidth: '200px',
        width: '30%',
        height: '800px',
        overflow: 'auto',
      }}
    >
      <Typography variant="h6">左侧区域</Typography>
      <Stack spacing={1}>
        {items.map((item) => (
          <div
            key={item.id}
            draggable={!disabledItems.includes(item.id)}
            onDragStart={(e) =>
              !disabledItems.includes(item.id) && onDragStart(e, item)
            }
            style={{
              padding: '8px',
              backgroundColor: disabledItems.includes(item.id)
                ? '#e0e0e0'
                : '#e3f2fd',
              borderRadius: '4px',
              textAlign: 'center',
              cursor: disabledItems.includes(item.id) ? 'not-allowed' : 'grab',
              opacity: disabledItems.includes(item.id) ? 0.5 : 1,
            }}
          >
            {item.name}
          </div>
        ))}
      </Stack>
    </Paper>
  );
};

export default LeftArea;

右侧区域 RightArea

import React from 'react';
import { DndContext, closestCenter } from '@dnd-kit/core';
import {
  SortableContext,
  arrayMove,
  verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { Paper, Stack, Typography } from '@mui/material';

import DraggableItem from './draggableItem';

const RightArea = ({ items, setItems }) => {
  const handleDragEnd = (event) => {
    const { active, over } = event;

    if (active.id !== over.id) {
      setItems((prevItems) => {
        const oldIndex = prevItems.findIndex((item) => item.id === active.id);
        const newIndex = prevItems.findIndex((item) => item.id === over.id);
        return arrayMove(prevItems, oldIndex, newIndex);
      });
    }
  };

  return (
    <Paper
      elevation={3}
      style={{
        padding: '16px',
        minWidth: '200px',
        width: '50%',
        height: '800px',
        overflow: 'auto',
      }}
    >
      <Typography variant="h6">右侧区域</Typography>
      <DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
        <SortableContext items={items} strategy={verticalListSortingStrategy}>
          <Stack spacing={1}>
            {items.map((item) => (
              <DraggableItem
                key={item.id}
                id={item.id}
                name={item.name}
                disabled={false}
              />
            ))}
          </Stack>
        </SortableContext>
      </DndContext>
    </Paper>
  );
};

export default RightArea;

拖拽项 DraggableItem

import React from 'react';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

const DraggableItem = ({ id, name, disabled }) => {
  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    padding: '8px',
    margin: '4px 0',
    backgroundColor: '#f0f0f0',
    borderRadius: '4px',
    textAlign: 'center',
    cursor: disabled ? 'not-allowed' : 'grab',
    opacity: disabled ? 0.5 : 1,
  };

  return (
    <div
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...(disabled ? {} : listeners)}
    >
      {name}
    </div>
  );
};

export default DraggableItem;

posted @   分页需带参  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示