Click on the front-end Q above to follow the official account
Reply to join the group, join the front-end Q technology exchange group
1. Introduction to usage
Based on the drag and drop function of react, there are several popular libraries:
-
react-dnd
-
react-beautiful-dnd
-
dnd-kit
-
react-sortable-hoc
React-dnd
(1) Basic concepts
-
Backend: The backend is mainly used to smooth out browser differences, handle DOM events, and convert DOM events into redux actions inside React DnD. You can use HTML5 to drag and drop the backend, or you can customize it Backend implementation of touch and mouse event simulation
-
Item: Use a data object to describe the currently dragged element, for example { cardId: 42 }
-
Type: Similar to the actions types enumeration constant in redux, it defines the drag and drop types supported in the application
-
Monitor: Drag and drop is inherently stateful. Either a drag operation is in progress, or it isn’t. Either there is the current type and the current item, or not, React DnD uses Monitor to store these states and provide queries
-
Connector: Connect components and Backend, allowing Backend to get DOM
-
DragSource: This is a high-level component, use it to wrap your component to make it a drag source
-
DropTarget: This is a high-level component, use it to wrap your component to make it a drop source
-
DragDropContext: Wraps the root component and provides a drag-and-drop context
(2) Simple demo
codesandbox.io/s/github/re…[1]
react-beautiful-dnd
(1) Basic concepts
It mainly contains three components.
-
DragDropContext : Used to wrap the dragging root component, both Draggable and Droppable need to be wrapped in DragDropContext
-
Draggable is used to wrap the components you need to drag, so that the components can be dragged (make it draggable)
-
Droppable is used to wrap components that receive dragged elements, so that components can be placed (dropped on it)
(2) Simple demo
https://juejin.cn/post/codesandbox.io/s/k260nyxq9v
dnd-kit
(1), basic concepts
1. DndContext is used to wrap the drag root component, both Draggable and Droppable need to be wrapped in DndContext
2. Droppable is used to package components that receive dragged elements, so that components can be placed
3. Draggable is used to wrap the components you need to drag, so that the components can be dragged
4. Sensors are used to detect different input methods to initiate drag operations, respond to movement, and end or cancel operations. The built-in sensors are:
-
pointer
-
mouse
-
touch
-
keyboard
5. Modifiers allow you to dynamically modify the motion coordinates detected by the sensor. They can be used for a wide range of use cases such as:
-
Limit motion to a single axis
-
Constrains the movement of the draggable node container’s bounding rectangle
-
Constrains the movement of the draggable node’s scroll container’s bounding rectangle
-
Apply resistance or clamping motion
(2), simple demo
5fc05e08a4a65d0021ae0bf2-ffprtowwny.chromatic.com/iframe.html…[2]
react-sortable-hoc
(1), basic concepts
1. SortableContainer Drag and drop the sorted container
2. SortableElement drag and drop sorted elements
(2), simple demo
https://juejin.cn/post/codesandbox.io/s/react-sortable-hoc-starter-o104x95y86
3. Antd compatible table
How to use it with the table component of antd?
react-dnd uses antd-table :codesandbox.io/s/tuo-zhuai…[3]
react-sortable-hoc uses antd-table:codesandbox.io/s/tuo-zhuai…[4]
react-beautiful-dnd-antd-table: codesandbox.io/s/react-bea…[5]
dnd-kit: stackblitz.com/edit/react-…[6] (the demo does not work, github.com/clauderic/d…[7] According to this issue, it is the reason of antd-design itself,
Enhanced table component under the hood)
4. Tree compatible
Antd’s own tree drag and drop sorting:
codepen.io/huxinmin/em…[8]
The disadvantage of the built-in tree drag is
-
The effect of dynamic real-time dragging and changing positions cannot be realized, and the position change must occur after the dragging is completed
-
Need to modify a lot of built-in styles
Trees can simply be thought of as lists nested within each other.
react-dnd: codesandbox.io/s/crazy-hoo…[9]
react-sortable-hoc:codesandbox.io/embed/react…[10]
react-beautiful-dnd-antd-table:codesandbox.io/embed/react…[11]
dnd-kit:codesandbox.io/embed/react…[12]
5. Mobile compatibility
react-dnd: codesandbox.io/embed/react…[13]
react-beautiful-dnd-antd-table: codesandbox.io/s/react-bea…[14]
react-sortable-hoc uses antd-table:codesandbox.io/s/tuo-zhuai…[15]
dnd-kit:5fc05e08a4a65d0021ae0bf2-hbqxtqukzi.chromatic.com/iframe.html…[16]
6. Infinite scroll
The best way is to use virtual-list, but the support of these libraries is also different.
react-dnd:codesandbox.io/embed/react…[17]
Use requestAnimationFrame for performance optimization, and can also be used with other virtual list libraries.
dnd-kit:5fc05e08a4a65d0021ae0bf2-hbqxtqukzi.chromatic.com/iframe.html…[18]
This demo uses the react-tiny-virtual-list [19] library.
react-sortable-hoc:clauderic.github.io/react-sorta…[20]
Using react-virtualized
react-beautifule-dnd:react-beautiful-dnd.netlify.app/iframe.html…[21]
React-virtualized is used.
7. Summary comparison
-
react-dnd[22]
-
complete documentation
-
github star number 16.4k
-
The maintenance and update are good, and there has been an update and maintenance in the last month
-
higher learning costs
-
Moderate function
-
Mobile compatibility, good
-
Moderate number of examples
-
Many concepts, complicated to use
-
Components can be decoupled
-
react-beautiful-dnd[23]
-
complete documentation
-
github star number 24.8k
-
The maintenance and update are good, and there have been updates and maintenance in the last three months
-
higher learning costs
-
Moderate ease of use
-
feature rich
-
Excellent mobile compatibility
-
Lots of examples
-
is a higher-level abstraction built specifically for vertical and horizontal lists, without the extensive functionality that react-dnd provides
-
Beautiful appearance, good accessibility, physical perception makes people feel more realistic when moving objects
-
The development concept is drag and drop, does not support copy/clone
-
dnd-kit[24]
-
complete documentation
-
github star number 2.8k
-
The maintenance and update are good, and there has been an update and maintenance in the last month
-
Moderate cost of study
-
Moderate ease of use
-
Moderate function
-
Mobile Compatibility, Moderate
-
Lots of examples
-
copy/clone not seen
-
react-sortable-hoc[25]
-
less documentation
-
github star number 9.5k
-
The maintenance and update are good, and there have been updates and maintenance in the last three months
-
lower learning costs
-
Ease of use
-
simple function
-
Mobile Compatibility, Moderate
-
Moderate number of examples
-
Drag and drop to another container is not supported
-
copy/clone not seen
-
Mainly focus on the sorting function, and the rest of the drag and drop functions are not rich
If it is to be used in combination with antd’s table, the simplest component is react-sortable-hoc. For infinite scrolling, although there are many examples of react-sortable-hoc, but few source codes, you can consider using react-beautiful-dnd. If it is a tree-like drag and drop, you can use the tree that comes with antd if the requirements are not high, and react-beautiful-dnd if you require high points. Compatible with mobile terminals, you can consider using react-sortable-hoc or react-beautiful-dnd.
8. How to encapsulate a simple drag and drop component by yourself
1. HTML5 drag and drop API
First, to make the element draggable, the draggable property needs to be set:
<img draggable="true">
Then there are several drag and drop processing functions:
-
ondrag drag and drop in progress
-
ondragend/ondragstart start drag and drop and end drag and drop
-
ondragover When the element or selected text is dragged over a target target (fires every 100 ms).
-
ondraenter/ondragleave the source object starts entering/leaving the range of the target object
-
ondrop The source object is dragged and dropped on the target object
For data transfer, use event.dataTransfer, which has the following APIs:
-
setData: Add drag data, this method receives two parameters, the first parameter is the data type (customizable), the second parameter is the corresponding data
-
getData: Reverse operation, get data, only receive one parameter, namely the data type
-
clearData: clear data
-
setDragImage: You can customize the image next to the mouse during drag and drop
-
The effectAllowed: attribute specifies an effect that is allowed for drag and drop operations. The copy operation is used to indicate that the data being dragged will be copied from the current location to the dropped location. The _move operation is used to specify that the data being dragged will be moved. The link_action is used to indicate that some form of relationship or connection will be created between the source and the drop location.
2. Function and architecture design
-
Use react-hooks
-
Drag and drop object drag component, drag and drop object drop component, drag and drop context dndContext
-
Support mobile terminal
-
Support sorting
3. Code
The Drag component uses:
<Drag index={1} id='1'> <div>Wrapped draggable components</div> </Drag>
Drag component implementation:
import { FC } from "react"; interface DragProps { index: number; id: string | number; } const Drag: FC<DragProps> = (props) => { const startDrag = (ev) => { // transfer data ev.dataTransfer.setData("index", props.index); ev.dataTransfer.setData("id", props.id); }; return ( <div draggable onDragStart={startDrag}> {props. children} </div> ); }; export default Drag;
The Drop component uses:
<Drop> <Drag index={1} id='1'> <div>Wrapped draggable components</div> </Drag> </Drop>
Drop component implementation:
import { FC, useContext } from "react"; import { Context } from "./DndContext"; const Drop: FC = (props) => { const { onDragOver, onDragEnd } = useContext(Context); const dragOver = (ev) => { ev.preventDefault(); if (onDragOver) onDragOver(); }; const drop = (ev) => { // retrieve data const oldIndex = ev.dataTransfer.getData("index"); // Get the Y-axis coordinate at the end of the drag const Y = ev.clientY; // Simple calculation, set the height to 20 // I'm lazy here, the actual calculation is very complicated //Generally, there are two implementation ideas, one is to calculate based on the position, and the other is to set the drag source to be placed, and then get const height = 20; const newIndex = Math. floor(Y / height); if (oldIndex) { if (onDragEnd) onDragEnd(Number(oldIndex), newIndex); } }; return ( <div onDragOver={dragOver} onDrop={drop}> {props. children} </div> ); }; export default Drop;
The DndContext component uses:
<DndContext onDragEnd={(oldIndex, newIndex) => { setData(arrayMove(data, oldIndex, newIndex)); }} onDragOver={() => {}} > <Drop> {data. map((i, index) => ( <Drag key={i.id} id={i.id} index={index}> <div className="item">{i.text}</div> </Drag> ))} </Drop> </DndContext>
DndContext component implementation:
import { createContext, FC } from "react"; export interface TContext { onDragOver: () => void; onDragEnd: (oldIndex: number, newIndex: number) => void; } const Context = createContext<TContext>({} as TContext); const DndContext: FC<TContext> = (props) => { return ( <Context.Provider value={<!-- -->{ onDragEnd: (oldIndex, newIndex) => { props.onDragEnd(oldIndex, newIndex); }, onDragOver: () => { props.onDragOver(); } }} > {props. children} </Context.Provider> ); }; export { Context }; export default DndContext;
If you need to deal with mobile compatibility, you can use the following libraries:
github.com/timruffles/…[26]
Fourth, optimize space
-
After dragging and dropping, the position is calculated
-
Real-time exchange position during dragging
-
performance optimization
-
exception handling etc.
-
drag process style
-
Drag direction, x-axis and y-axis
-
etc.
5. Online code
Specific online code example: codesandbox.io/embed/react…[27]
Author: green fire
Article address: https://juejin.cn/post/7062625911312646175
Previous recommendations The details of async and await devils that you don't know Hurry up! The Tencent WeChat team is recruiting, and the resume will be sent directly to the interviewer! collect! The most comprehensive Vue front-end code style guide in history at last Welcome to add me on WeChat, pull you into the technology group, long-term exchange and learning... Welcome to pay attention to "Front-end Q", study the front-end seriously, and be a professional technical person... Click to watch and support me