Я уже писал статью об использовании react-dnd, которая может быть многословной, но содержание более подробное, и перечислены многие API. В настоящее время React Hooks отсутствует, и react-dnd также был соответствующим образом обновлен, поэтому в этой статье используются React Hooks + TypeSscript для реорганизации использования react-dnd.
предисловие
Введение в текущую версию
-
react
:16.9.0
-
react-dom
:16.9.0
-
typescript
:3.5.3
-
react-dnd
:9.3.4
-
react-dnd-html5-backend
:9.3.4
используется для строительных лесовcreate-react-app
, установлено глобальноcreate-react-app
Команда:npm i create-react-app -g
Строительство окружающей среды
- Создать подмости:
npx create-react-app react-dnd-hooks --typescript
- Установить
react-dnd
:yarn add react-dnd
- Установить
react-dnd-html5-backend
:yarn add react-dnd-html5-backend
Для удобства унификации идентификатора «перетаскиваемый компонент» заменяется на «перетаскиваемый компонент», а «целевой принимающий компонент» заменяется на «отбрасываемый компонент».
1. Оберните корневой узел с помощью DndProvider
хочу использоватьreact-dnd
Для операций перетаскивания вам необходимо использоватьDndProvider
Метка оборачивает корневой узел и проходит вbackend
параметр:index.tsx
документ
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'));
2. Позвольте элементам двигаться
Например, сейчас есть компонент Box, и мы хотим его перетащить.На данный момент давайте сначала объявим этот компонент.
Создайте компонент Box
Box.tsx
import React, { CSSProperties } from 'react';
const style: CSSProperties = {
width: 200,
height: 50,
lineHeight: '50px',
background: 'pink',
margin: '30px auto'
}
const Box = () => {
return (
<div style={ style }>可拖拽组件 Box</div>
)
}
export default Box;
В настоящее время мы используем мышь, чтобы удерживать компонент Box, и обнаруживаем, что нет возможности перетащить компонент Box.
Анимация компонента Box
использоватьreact-dnd
который предоставилuseDrag
, первое возвращаемое значение — это объект, возвращаемый методом collect (здесь он не используется, поэтому опущен), а второе возвращаемое значение — это ref, который присваивается элементу, который вы хотите перетащить для достижения перетаскивания компонента.Box.tsx
...
import { useDrag } from 'react-dnd';
...
const Box = () => {
// 使用 useDrag
const [, drager] = useDrag({
item: { type: 'Box' }
})
return (
// 将第二个参数赋值给 ref
<div ref={ drager } style={ style }>可拖拽组件 Box</div>
)
}
export default Box;
В это время мы можем использовать мышь для перетаскивания туда и обратноBox
Компонент готов, но его можно только тащить, а датчик некуда братьBox
компонент, давайте посмотрим, как он работает.
3. Создайте компонент мусорной корзины, чтобы получить компонент перетаскивания.
использоватьreact-dnd
который предоставилuseDrop
, первое возвращаемое значение — это объект, возвращаемый методом collect, а второе возвращаемое значение — это ссылка, которая присваивается объекту, который вы хотите получить.drop
Компонент может воспринимать компонент перетаскивания.
Dustbin
Компоненты:
import React, { CSSProperties } from 'react';
import { useDrop, DropTargetMonitor } from 'react-dnd';
const style: CSSProperties = {
width: 400,
height: 400,
margin: '100px auto',
lineHeight: '60px',
border: '1px dashed black'
}
const Dustbin = () => {
// 第一个参数是 collect 方法返回的对象,第二个参数是一个 ref 值,赋值给 drop 元素
const [collectProps, droper] = useDrop({
// accept 是一个标识,需要和对应的 drag 元素中 item 的 type 值一致,否则不能感应
accept: 'Box',
// 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>
)
}
export default Dustbin;
Напоминание: не забудьте сослаться на компоненты Box и Dustbin на компонент App.tsx для использования.
В-четвертых, карта эффектов
5. Другие часто используемые API и меры предосторожности
-
drag
Часто используемые свойства компонентов:-
item
: это объект, должен бытьtype
Атрибуты -
begin(mintor: DragSourceMonitor)
: Компонент начинает перетаскивание и должен вернуть объект, содержащийtype
свойства, будет переопределятьitem
Объект, возвращаемый свойством, будет передан в первый параметр методов hover и drop компонента drop. -
end(item, mintor: DragSourceMonitor)
: срабатывает, когда компонент перестает перетаскиваться,item
даdrop
компонент вdrop
Объект, возвращаемый при выполнении метода, эквивалентенmintor.getDropResult()
значение
-
-
drop
Часто используемые свойства компонентов-
accept
: строка, должна соответствоватьdrag
компонентitem
в атрибутеtype
значение соответствует -
hover(item, minoter: DropTargetMonitor)
:drag
компонент вdrop
над компонентомhove
вызывать -
drop(item, minoter: DropTargetMonitor)
:drag
После перетаскивания компонента поместите его наdrop
Запускается при запуске компонента, возвращаемое значение будет передано в качестве параметра вdrag
компонентыend
первый параметр метода
-
-
Сделайте компонент перетаскиваемым и получайте перетаскиваемые элементы
import React, { useRef } from 'react';
import { useDrag, useDrop } from 'react-dnd'
const Card = () => {
const ref = useRef<HTMLDivElement>(null);
const [, drop] = useDrop({
accept: 'Card',
});
const [, drag] = useDrag({
item: { type: 'Card' }
});
// 使用 drag 和 drop 包装 ref
drag(drop(ref));
// 将变量 ref 传给元素的 ref 即可
return (<div ref={ ref }>既可以被拖动也可以接收拖动组件</div>)
}
-
drag
Компонент хочет передать некоторые данные- Передайте его напрямую, используя свойство item:
const [, drag] = useDrag({ item: { type: 'Card', id: 1, name: 'card1', kind: 'Card } });
- Используйте метод begin для передачи значений:
Примечание. Возвращаемое значение метода begin переопределяет атрибут элемента, поэтому обязательно передайте атрибут типа.
const [, drag] = useDrag({ item: { type: 'Card' }, begin(mintor: DragSourceMonitor) { return { type: 'Card', id: 1, name: 'card1', kind: 'Card } } });
- позже
dropTarget
В принимающем компоненте его можно получить в первом параметре метода наведения или сброса, либо использоватьDropTargetMonitor
изgetItem()
приобретение функции.
-
хочу получить
drag
компонент илиdrop
Некоторая информация о состоянии компонента-
drag
Компоненты:
// collect 函数返回的对象会赋给 useDrop 的第一个参数 collectProps,可以在组件中直接进行使用 const [collectProps, drag] = useDrag({ item: { type: 'Card', id: 1, name: 'card1', kind: 'Card }, collect: (minoter: DropTargetMonitor) => ({ isOver: minoter.isOver(), }) });
-
drop
Компоненты:
// collect 函数返回的对象会赋给 useDrop 的第一个参数 collectProps,可以在组件中直接进行使用 const [collectProps, droper] = useDrop({ accept: 'Box', collect: (minoter: DropTargetMonitor) => ({ isOver: minoter.isOver(), }) })
- API для получения дополнительной информации о статусе можно найти в моей предыдущей статье.API, связанный с DragSourceMonitorа такжеAPI, связанный с DropTargetMonitor
-
6. Более сложная демонстрация
Пример размещения с помощью перетаскивания и сортировки с помощью перетаскивания, заинтересованные друзья могут посмотреть.
визуализация
Демонстрационный адрес
Добро пожаловать Звезда! Добро пожаловать в Форк!