Day 272/300 React 实现DOM级别的拖拽的Demo

react-dnd

一款强大的 React 拖放库,支持多种拖放类型,提供了许多可复用的组件和钩子,可以方便地实现基本的拖放效果。

(一)安装

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

(二)源码

1、根节点

import React from 'react'
import App from './App'
import {
    
     DndProvider } from 'react-dnd'
import {
    
     HTML5Backend } from 'react-dnd-html5-backend'

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
    <DndProvider backend={
    
    HTML5Backend}>
        <App />
    </DndProvider>
)

2、子页面

import React from 'react';
import {
    
     HTML5Backend } from 'react-dnd-html5-backend'
import {
    
     useDrag,useDrop,DndProvider } from 'react-dnd'

interface DragComponentProps {
    
    
}
const DragComponent: React.FC<DragComponentProps> = () => {
    
    
    const matchDrag = useDrag({
    
    
      type: "FILE"
    });
    const matchDrop = useDrop({
    
    
      accept: "FILE",
      drop: function (item, monitor) {
    
    
        console.log("dropped");
      }
    });

    return (
        <div >
          <DndProvider backend={
    
    HTML5Backend}>
            <div ref={
    
    matchDrag[1]}>Drag</div>
          </DndProvider>
          <DndProvider backend={
    
    HTML5Backend}>
            <div ref={
    
    matchDrop[1]}>Drop</div>
          </DndProvider>
        </div>
    )
}

export default DragComponent

3、Demo2

上面的例子如果有多个起始节点,有问题;下面的可以有多个起始节点


import React from 'react';
import {
    
     HTML5Backend } from 'react-dnd-html5-backend'
import {
    
     useDrag,useDrop,DndProvider } from 'react-dnd'
const style = {
    
    
    border: '1px dashed gray',
    backgroundColor: 'white',
    padding: '0.5rem 1rem',
    marginRight: '1.5rem',
    marginBottom: '1.5rem',
    cursor: 'move',
    float: 'left',
};

const Box = (props) => {
    
    
    const {
    
     name } = props;

    const [{
    
     isDragging }, drag] = useDrag(() => ({
    
    
        type: 'box',
        item: () => ({
    
     name }),
        collect: (monitor) => ({
    
    
        isDragging: monitor.isDragging(),
        }),
        end: (item, monitor) => {
    
    
        // 拖拽元素放下时,drop 结果
        const dropResult = monitor.getDropResult();

        // 如果 drop 结果存在,就弹出 alert 提示
        if (dropResult) {
    
    
            alert(`You dropped ${
      
      item.name} into ${
      
      dropResult.name}!`);
        }
        },
    }));

    const opacity = isDragging ? 0.4 : 1;
    // 使用 connectDragSource 包裹住 DOM 节点,使其可以接受各种拖动 API
    // connectDragSource 包裹住的 DOM 节点才可以被拖动
    return (
        <div style={
    
    {
    
     ...style, opacity }} ref={
    
    drag}>
        {
    
    name}
        </div>
    );
};
const style2 = {
    
    
    height: '12rem',
    width: '12rem',
    marginRight: '1.5rem',
    marginBottom: '1.5rem',
    color: 'white',
    padding: '1rem',
    textAlign: 'center',
    fontSize: '1rem',
    lineHeight: 'normal',
    float: 'left',
  };
  
const Dustbin = () => {
    
    
    const [{
    
     canDrop, isOver }, drop] = useDrop(() => ({
    
    
      accept: 'box',
      collect: (monitor) => ({
    
    
        canDrop: monitor.canDrop(),
        isOver: monitor.isOver(),
      }),
      drop: () => ({
    
     name: 'Dustbin' }),
    }));
  
    const isActive = canDrop && isOver;
  
    let backgroundColor = '#222';
    // 拖拽组件此时正处于 drag target 区域时,当前组件背景色变为 darkgreen
    if (isActive) {
    
    
      backgroundColor = 'darkgreen';
    }
    // 当前组件可以放置 drag source 时,背景色变为 pink
    else if (canDrop) {
    
    
      backgroundColor = 'darkkhaki';
    }
  
    // 使用 connectDropTarget 包裹住 DOM 节点,使其可以接收对应的 drag source 组件
    // connectDropTarget 包裹住的 DOM 节点才能接收 drag source 组件
    return (
      <div ref={
    
    drop} style={
    
    {
    
     ...style2, backgroundColor }}>
        {
    
    isActive ? 'Release to drop' : 'Drag a box here'}
      </div>
    );
};
interface DragComponentProps {
    
    
}
const DragComponent: React.FC<DragComponentProps> = () => {
    
    
    return (
        <div >
          <DndProvider backend={
    
    HTML5Backend}>
            <Box name="Glass" />
            <Box name="Banana" />
            <Box name="Paper" />
            <Dustbin></Dustbin>
          </DndProvider>
        </div>
    )
}

export default DragComponent

参考文档

https://react-dnd.github.io/react-dnd/about

https://stackblitz.com/edit/react-ts-f5nxsy?file=index.tsx,components%2FBoard.tsx

https://juejin.cn/post/6844903801120358407

猜你喜欢

转载自blog.csdn.net/xinghuowuzhao/article/details/130985382
今日推荐