react hooks方式使用react-dnd 拖拽

1、环境准备
react-dnd
react-dnd-html5-backend

官网地址:React DnD

2、用 DndProvider 将根节点包裹起来
    

import React from 'react';
import ReactDOM from 'react-dom';
import { DndProvider } from 'react-dnd';
import HTMLBackend from 'react-dnd-html5-backend'
import './index.css';
import App from './App';

ReactDOM.render(
    <DndProvider backend={ HTMLBackend }>
        <App />
    </DndProvider>,
    document.getElementById('root'));


Item
React DnD 基于数据驱动,当拖放发生时,它用一个数据对象来描述当前的元素,比如{ cardId: 25 }

Type
类型类似于 redux 里面的actions types 枚举常量,定义了应用程序里支持的拖拽类型。

Monitor
拖放操作都是有状态的,React DnD 通过 Monitor 来存储这些状态并且提供查询
一个 DragSourceMonitor 实例。使用它来查询有关当前拖动状态的信息,例如当前拖动的项目及其类型,当前和初始坐标和偏移,以及它是否已被删除。
canDrag()
是否可以被拖拽。如果没有正在进行拖动操作,则返回 true


isDragging()
是否正在被拖动。如果正在进行拖动操作,则返回 true


getItemType()
返回标识当前拖动项的类型的字符串或ES6符号。 如果没有拖动项目,则返回 null


getItem()
返回表示当前拖动项的普通对象。 每个拖动源都必须通过从其beginDrag()方法返回一个对象来指定它。 如果没有拖动项目,则返回 null


getDropResult()
返回表示最后记录的放置 drop result 对象


Connector
Backend 关注 DOM 事件,它应该返回一个普通的道具对象注入你的组件,组件关注拖放状态,connector 可以连接组件和 Backend ,可以让 Backend 获取到 DOM。
3、使用 react-dnd 提供的 useDrag进行拖放操做,

import { useDrag } from 'react-dnd';
...
const Box = () => {
    // 使用 useDrag
    const [, drager, dragPreview] = useDrag(() => ({
        // 必需的。这必须是字符串或符号。只有为相同类型注册的放置目标才会对此项目做出反应
        type: "Box",
        // 必需的(对象或函数)
        // 1.当这是一个对象时,它是一个描述被拖动数据的纯 JavaScript 对象。这是拖放目标唯一可用的关于拖动源的信息
        // 2.当这是一个函数时,它在拖动操作开始时被触发并返回一个表示拖动操作的对象(参见第一个项目符号)。如果返回null,则取消拖动操作
        item: (monitor) => {
            return {
                monitor,
                type: "box",
                item,
            };
        },
        // 组件停止拖拽时触发,item 是 drop 组件在 drop 方法执行时返回的对象,等同于 mintor.getDropResult() 的值
        end: (_item, monitor) => {
           
        },
        options: {
            dropEffect: "move",
        },
        collect: (monitor) => {
           
            return {
                isDragging,
            };
        },
    }));
    return (
        // 将第二个参数赋值给 ref
        <div ref={ drager } style={ style }>可拖拽组件 Box</div>
    )
}

export default Box;

drag 组件常用的属性:
item:是一个对象,必须要有一个 type 属性


begin(mintor: DragSourceMonitor):组件开始拖拽,必须返回一个对象包含 type 属性,会覆盖 item 属性返回的对象,会被传入 drop 组件 hover 和 drop 方法的第一个参数


end(item, mintor: DragSourceMonitor): 组件停止拖拽时触发,item 是 drop 组件在 drop 方法执行时返回的对象,等同于 mintor.getDropResult() 的值

canDrag(item, monitor)** 重载是否可以拖拽的方法    可选的。用它来指定当前是否允许拖动。如果您想要始终允许它,只需省略此方法即可。注意:您可能无法调用monitor.canDrag() 此方法。

isDragging(item, monitor)** 可以重载是否正在拖拽的方法    可选的。默认情况下,仅启动拖动操作的拖动源被视为拖动。注意:您可能无法调用 monitor.isDragging() 此方法

4、使用 react-dnd 提供的 useDrop用来接收 drag 组件,放置目标操作

const Dustbin = () => {
    // 第一个参数是 collect 方法返回的对象,第二个参数是一个 ref 值,赋值给 drop 元素
    const [collectProps, droper] = useDrop({
        // accept 是一个标识,需要和对应的 drag 元素中 item 的 type 值一致,否则不能感应
        accept: 'Box',
        // drag 组件在 drop 组件上方 hove 时触发
        // hover: (item, monitor) => {
        // },
        // drag 组件拖拽结束后,放到 drop 组件时触发,返回的值会作为参数传递给 drag 组件 end 方法    的第一个参数
        drop: (item, monitor) => {
            return {
                item,
                monitor,
            };
        },
        // collect 函数,返回的对象会成为 useDrop 的第一个参数,可以在组件中直接进行使用
        collect: (minoter: DropTargetMonitor) => ({
            isOver: minoter.isOver()
        })
    })
    const bg = collectProps.isOver ? 'deeppink' : 'white';
    const content = collectProps.isOver ? '快松开,放到碗里来' : '将 Box 组件拖动到这里'
    return (
        // 将 droper 赋值给对应元素的 ref
        <div ref={ droper } style={{ ...style, background: bg }}>{ content }</div>
    )
}


drop 组件常用的属性:
accept:字符串,必须和对应 drag 组件的 item 属性中的 type 值一致


hover(item, minoter: DropTargetMonitor):drag 组件在 drop 组件上方 hove 时触发


drop(item, minoter: DropTargetMonitor):drag 组件拖拽结束后,放到 drop 组件时触发,返回的值会作为参数传递给 drag 组件 end 方法的第一个参数

canDrop(item, monitor) 重载是否可以 drop 的方法

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值