美文网首页
React Dnd 基本拖放功能实现及 API 整理

React Dnd 基本拖放功能实现及 API 整理

作者: VioletJack | 来源:发表于2020-07-05 16:35 被阅读0次

创建项目

$ mkdir myapp && cd myapp
$ yarn create @umijs/umi-app
$ yarn add react-dnd react-dnd-html5-backend

简单了解 API

DndProvider

一个容器,在这个容器中的元素可以进行拖放的操作。

import { HTML5Backend } from 'react-dnd-html5-backend'
import { DndProvider } from 'react-dnd'

export default class YourApp {
  render() {
    return (
      <DndProvider backend={HTML5Backend}>
        /* Your Drag-and-Drop Application */
      </DndProvider>
    )
  }
}

useDrag

一个 hook 函数,可以让一个 DOM 元素实现拖拽效果。

import { useDrag } from 'react-dnd'

function DraggableComponent(props) {
  const [collectedProps, drag] = useDrag({
    item: { id, type }
  })
  return <div ref={drag}>...</div>
}

useDrop

一个 hook 函数,可以让一个 DOM 元素能够放置拖拽元素。

import { useDrop } from 'react-dnd'

function myDropTarget(props) {
  const [collectedProps, drop] = useDrop({
    accept
  })

  return <div ref={drop}>Drop Target</div>
}

一个简单的栗子

import React from 'react';
import styles from './index.less';
import { useDrop, useDrag, DndProvider } from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'

const ItemTypes = {
  APP: 'demo-app'
}

const Child = () => {
  const [{ isDragging }, drag] = useDrag({
    item: { type: ItemTypes.APP },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  })

  return <div className={styles.child} style={{ opacity: isDragging ? 0.5 : 1 }} ref={drag}>
    Child
  </div>
}

const Container = () => {
  const [{ isOver }, drag] = useDrop({
    accept: ItemTypes.APP,
    collect: (monitor) => ({
      isOver: monitor.isOver(),
    }),
  })

  return <div className={styles.container} ref={drag} style={{ background: isOver ? '#FFAA00' : '#FFFFFF' }}>
    Container
  </div>
}

export default () => {
  return (
    <DndProvider backend={HTML5Backend}>
      <div className={styles.app}>
        <Container />
        <Child />
      </div>
    </DndProvider>
  );
}

.app {
  background: #FFFFFF;
}

.container {
  border: #CCCCCC solid 1px;
  width: 300px;
  height: 300px;
}

.child {
  border: #CCCCCC solid 1px;
  display: inline-block;
  margin: 5px;
  width: 50px;
  height: 50px;
}

用到的三个 API 梳理

简单梳理下所有的 API

useDrag

这个 hook 函数返回一个数组。
index 0 一个对象,它是从配置中的 collect 函数来定义的。
index 1 一个连接器函数,用在 React 的 ref 属性。连接了能够拖拽的元素。
index 2 一个连接器函数,用在 React 的 ref 属性。连接了会被拖拽的元素。
PS; 1 和 2 可以用来实现拖拽元素 A 中的元素 B,元素 A 跟着移动。

下面是 Hook 函数中的配置对象元素:

  • item 必填属性,它是一个纯 JavaScript 对象。这个对象中必须传的是 type 属性。另外的一个作用是传递拓转元素中的数据。可以在拓转完成函数 end 中拿到数据做后续处理。
  • item.type 必填属性,只有 drag 和 drop 中的 type 相才能实现拖放。
  • previewOptions 预览配置对象?
  • options 配置对象
  • begin(monitor) 拖拽开始事件,一般不需要返回,如果有 return 会替换 item
  • end(item, monitor) 拖拽结束事件
  • canDrag(monitor) 定义能否拖拽的函数。
  • isDragging(monitor) 用于重写定义正在拖拽中的状态。,一般不用改。
  • collect 收集函数,必须返回一个对象。具体配置可参照 DragSourceMonitor,它返回的对象可以在 index 0 对象中拿到。

个人感觉 item 和 collect 最常用,begin 函数和 end 函数也比较常用。梳理下来还是挺简单的。

useDrop

这个 hook 函数返回一个数组:

index 0 collect 函数返回的对象,如果没有对象可以返回空。
index 1 一个连接器函数,用在 React 的 ref 属性。连接了能够放置的元素。

下面是配置对象元素:

  • accept必填项,定义了一个可以接收的拖拽元素的类型。(就是 useDrag 中的 item.type)
  • options 配置对象
  • drop(item, monitor) 放置 drag 元素事件
  • hover(item, monitor) drag 元素进入 drop 元素事件。
  • canDrop(item, monitor) 定义是否能否放置的函数。如果使用默认方式,不需要定义。
  • collect 收集函数,必须返回一个对象。具体配置参照 DropTargetMonitor,它返回的对象会出现在 index 0

DndProvider

这是一个 React 容器组件,在这个容器组件中的元素才可以实现拖放。

它一共三个 props:

  • backend 必要属性,React Dnd backend,一般都会使用 HTML5 backend
  • context backend context 配置。具体要看 backend 库的定义。
  • options backend 配置对象,具体要看 backend 库的定义。

最后

暂时就这么多,简单写了个 demo,然后了解了一下用到的 API。其实仔细了解之下还是蛮简单的。还有 useDragLayerDragPreviewImage 两个 API 没用到,但应该都不难。
明天我试着写个更加复杂的例子分享出来。

相关文章

网友评论

      本文标题:React Dnd 基本拖放功能实现及 API 整理

      本文链接:https://www.haomeiwen.com/subject/oqxvqktx.html