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

React-dnd是一个强大的React库,用于实现拖放功能。它提供了DndProvider、useDrag和useDrop等工具,支持HTML5后端,可以方便地创建可拖放的组件。示例代码展示了如何设置拖放区域以及处理拖放事件。
摘要由CSDN通过智能技术生成

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值