Home  >  Article  >  Web Front-end  >  How react-dnd implements drag and drop

How react-dnd implements drag and drop

WBOY
WBOYOriginal
2022-04-29 16:49:582969browse

Implementation method: 1. Use "import{DndProvider}from 'react-dnd'" to define a draggable range; 2. Use "import{useDrag}from 'react-dnd'" to wrap the DragSource Just hold the component so it can be dragged.

How react-dnd implements drag and drop

The operating environment of this tutorial: Windows 10 system, react17.0.1 version, Dell G3 computer.

How to implement drag and drop with react-dnd

React DnD is a set of React high-order components created by Dan Abramov, the core author of React and Redux, which can help build complex components while keeping components separated. Drag and drop interface.

Requirements for React DnD

  • Uses HTML5 drag and drop API by default, but supports

  • Do not directly operate the DOM

  • ##DOM and drag-and-drop source and target decoupling

  • Incorporate the stealing type into HTML5 drag-and-drop Ideas on matching and data passing

##Features of React DnD

Focus on drag and drop, no ready-made Components

React DnD provides a set of powerful primitives, but it does not contain any ready-made components. Instead, it wraps the user's components and injects props. It is lower-level than jQuery UI, etc., focusing on making drag-and-drop interactions correct, and leaving visual effects such as coordinate restrictions to the user. This is actually a principle of separation of concerns. For example, React DnD does not intend to provide sortable components, but users can quickly develop any required custom sortable components based on it.

One-way data flow

adopts declarative rendering similar to React, and adopts one-way data flow architecture like redux. In fact, Redux is used internally

Hide issues with the platform’s underlying API

The HTML5 drag-and-drop API is full of pitfalls and browser inconsistencies. React DnD handles them internally for you, so users can focus on developing applications instead of solving browser issues.

Extensible and testable

React DnD provides an HTML5 drag-and-drop API wrapper by default, but it also allows you to provide a custom "backend". You can create a custom DnD backend based on touch events, mouse events, or other things. For example, the built-in mocking backend allows you to test drag-and-drop interactions of components in a Node environment.

Ready for the future

React DnD does not export mixins and works equally well with any component, whether they use ES6 classes, createReactClass or other React frameworks Created. And the API supports ES7 decorators.

Examples are as follows: 1.1. Use DndProvider to define a draggable range

/*
 * @Author: muge
 * @Date: 2021-12-04 16:59:25
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-12-08 14:24:47
 */
import React, { useState } from 'react';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import SourceBox from './SourceBox';
import TargetBox from './TargetBox';
import TreeBox from './TreeBox';
const item: any[] = [
  {
    id: 1,
    name: 'muge',
  },
  {
    id: 2,
    name: 'muxi',
  },
  {
    id: 3,
    name: 'mugege',
  },
];
const Container = () => {
  // 当前拖拽项
  const [currentList, setCurrentList] = useState<any>({});
  return (
    // 类似redux数据传输  需要在最外层包裹对象
    <DndProvider backend={HTML5Backend}>
      <h1>拖拽源组件 列表-----树</h1>
      <div style={{ display: &#39;flex&#39; }}>
        <div>
          {/* 列表拖拽源 */}
          {item.map((itemz: any, index: number) => (
            <SourceBox setCurrentList={setCurrentList} item={itemz} key={index} />
          ))}
        </div>
        {/* 注意,不要树组件整体直接设置拖拽,抽成一个组件来遍历每一项 =》自定义渲染*/}
        {/* 树形拖拽源 */}
        <TreeBox />
      </div>
      <h1>拖拽放置目标</h1>
      {/* 拖拽最终放置组件 */}
      <TargetBox currentList={currentList} />
    </DndProvider>
  );
};
export default Container;

2. Use DragSource package Wrap the component so it can be dragged

/*
 * @Author: muge
 * @Date: 2021-12-07 14:26:08
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-12-08 14:18:52
 */
import { useDrag } from &#39;react-dnd&#39;;
const ItemTypes = {
  BOX: &#39;box&#39;,
};
const style = {
  border: &#39;1px dashed gray&#39;,
  backgroundColor: &#39;white&#39;,
  padding: &#39;0.5rem 1rem&#39;,
  marginRight: &#39;1rem&#39;,
  marginBottom: &#39;1rem&#39;,
  cursor: &#39;move&#39;,
};
const SourceBox = ({ item, setCurrentList }: any) => {
  const [{ opacity }, drag] = useDrag(
    () => ({
      type: ItemTypes.BOX,
      collect: (monitor) => ({
        opacity: monitor.isDragging() ? 0.4 : 1,
      }),
      item: () => item, //返回当前列表项数据
      canDrag: (monitor) => {
        //是否取消拖拽
        console.log(monitor, &#39;monitor131&#39;);
        return true;
      },
      //
      end(currentItem, monitor) {
        // monitor.getDropResult(); //获取拖拽对象所处容器的数据
        // monitor.didDrop(); // 当前容器能否放置拖拽对象 拖动停止时触发
        monitor.didDrop() && setCurrentList(currentItem); //在容器点松开 才赋值
      },
    }),
    [],
  );
  return (
    <div ref={drag} style={{ ...style, opacity }}>
      {item.id}------{item.name}
    </div>
  );
};
export default SourceBox;

3. Use DropTarget to wrap the component so it reacts to dragging, hovering, or dropped compatible items.

/*
 * @Author: muge
 * @Date: 2021-12-07 14:26:08
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-12-08 14:33:08
 */
import React from &#39;react&#39;;
import { useDrop } from &#39;react-dnd&#39;;
const ItemTypes = {
  BOX: &#39;box&#39;,
};
const style: any = {
  border: &#39;1px solid gray&#39;,
  height: &#39;15rem&#39;,
  width: &#39;15rem&#39;,
  padding: &#39;2rem&#39;,
  textAlign: &#39;center&#39;,
};
const TargetBox = ({ currentList }: any) => {
  const [{ isActive, isOver, canDrop }, drop] = useDrop(() => ({
    accept: ItemTypes.BOX,
    collect: (monitor) => ({
      isActive: monitor.canDrop() && monitor.isOver(),
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop(),
    }),
    // hover: (item, monitor) => {
    //   console.log(item, &#39;item&#39;);
    //   console.log(monitor, &#39;monitor&#39;);
    // },
  }));
  // console.log(isOver, &#39;isOver&#39;);
  // console.log(canDrop, &#39;canDrop&#39;);
  return (
    <div ref={drop} style={style}>
      {isActive ? &#39;Release to drop&#39; : &#39;Drag item here&#39;}
      <div
        style={{
          backgroundColor: &#39;pink&#39;,
          height: 30,
          display: &#39;flex&#39;,
          alignItems: &#39;center&#39;,
          justifyContent: &#39;center&#39;,
          fontSize: 17,
          fontWeight: 600,
          width: &#39;100%&#39;,
        }}
      >
        {JSON.stringify(currentList) !== &#39;{}&#39; ? JSON.stringify(currentList) : &#39;当前item&#39;}
      </div>
    </div>
  );
};
export default TargetBox;

Drag and drop to this list to complete

Recommended learning: "

react video tutorial

"

The above is the detailed content of How react-dnd implements drag and drop. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn