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

2020-07-05  本文已影响0人  VioletJack

创建项目

$ 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 和 collect 最常用,begin 函数和 end 函数也比较常用。梳理下来还是挺简单的。

useDrop

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

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

下面是配置对象元素:

DndProvider

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

它一共三个 props:

最后

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

上一篇 下一篇

猜你喜欢

热点阅读