首页 > 其他分享 >使用React、Js、Mui实现拖拽功能

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

时间:2024-12-03 14:32:08浏览次数:9  
标签:const name Item Js React item import Mui id

使用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;

标签:const,name,Item,Js,React,item,import,Mui,id
From: https://www.cnblogs.com/sxliu414/p/18584009

相关文章