Как использовать API перетаскивания HTML в React

[ad_1]
⭐
Как использовать API перетаскивания HTML в React
В этом руководстве мы создадим компонент перетаскивания React для загрузки файлов и изображений. В процессе мы узнаем об API перетаскивания HTML. Мы также узнаем, как использовать хук useReducer для управления состоянием в функциональном компоненте React.
API перетаскивания — одна из самых крутых функций HTML. Это помогает нам реализовать функции перетаскивания в веб-браузерах.
В текущем контексте мы будем перетаскивать файлы из-за пределов браузера. При удалении файлов мы помещаем их в список и отображаем их имена. Имея файлы на руках, мы могли бы затем выполнить какую-либо другую операцию с файлами, например, загрузить их на облачный сервер.
В этом руководстве мы сосредоточимся на том, как реализовать действие перетаскивания в приложении React. Если вам нужна простая JavaScript
реализации, возможно, вы сначала захотите прочитать «Как сделать загрузчик файлов с помощью перетаскивания с помощью ванильного JavaScript», отличный учебник, написанный Джозефом Циммерманом не так давно.
То dragenter
, dragleave
, dragover
, И drop
События
Существует восемь различных событий перетаскивания. Каждый из них срабатывает на разных этапах операции перетаскивания. В этом уроке мы сосредоточимся на четырех, которые срабатывают, когда предмет попадает в зону сброса: dragenter
, dragleave
, dragover
и drop
.
- То
dragenter
событие срабатывает, когда перетаскиваемый элемент попадает в допустимую цель перетаскивания. - То
dragleave
событие срабатывает, когда перетаскиваемый элемент покидает допустимую цель перетаскивания. - То
dragover
событие срабатывает, когда перетаскиваемый элемент перетаскивается по допустимой цели перетаскивания. (Он срабатывает каждые несколько сотен миллисекунд.) - То
drop
событие срабатывает, когда элемент падает на допустимую цель перетаскивания, т.е. перетаскивается и отпускается.
Мы можем превратить любой HTML-элемент в допустимую цель перетаскивания, определив ondragover
и ondrop
атрибуты обработчика событий.
Вы можете узнать все о восьми событиях из веб-документов MDN.
События перетаскивания в React
Для начала клонируйте репозиторий учебника по этому URL-адресу:
https://github.com/chidimo/react-dnd.git
Проверьте 01-start
филиал. Убедитесь, что у вас есть yarn
также установлен. Вы можете получить его на сайте yarnpkg.com.
Но если хотите, создайте новый проект React и замените содержимое App.js с кодом ниже:
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
<h1>React drag-and-drop component</h1>
</div>
);
}
export default App;
Также замените содержимое App.css с приведенным ниже стилем CSS:
.App {
margin: 2rem;
text-align: center;
}
h1 {
color: #07F;
}
.drag-drop-zone {
padding: 2rem;
text-align: center;
background: #07F;
border-radius: 0.5rem;
box-shadow: 5px 5px 10px #C0C0C0;
}
.drag-drop-zone p {
color: #FFF;
}
.drag-drop-zone.inside-drag-area {
opacity: 0.7;
}
.dropped-files li {
color: #07F;
padding: 3px;
text-align: left;
font-weight: bold;
}
Если вы клонировали репозиторий, введите следующие команды (по порядку), чтобы запустить приложение:
yarn # install dependencies
yarn start # start the app
Следующим шагом является создание компонента перетаскивания. Создать файл DragAndDrop.js внутри src/
папка. Введите следующую функцию внутри файла:
import React from 'react';
const DragAndDrop = props => {
const handleDragEnter = e => {
e.preventDefault();
e.stopPropagation();
};
const handleDragLeave = e => {
e.preventDefault();
e.stopPropagation();
};
const handleDragOver = e => {
e.preventDefault();
e.stopPropagation();
};
const handleDrop = e => {
e.preventDefault();
e.stopPropagation();
};
return (
<div className={'drag-drop-zone'}
onDrop={e => handleDrop(e)}
onDragOver={e => handleDragOver(e)}
onDragEnter={e => handleDragEnter(e)}
onDragLeave={e => handleDragLeave(e)}
>
<p>Drag files here to upload</p>
</div>
);
};
export default DragAndDrop;
В ответ div
, мы определили наш фокус HTML
атрибуты обработчика событий. Вы можете видеть, что единственное отличие от чистого HTML
это верблюжья оболочка.
То div
теперь является допустимой целью перетаскивания, так как мы определили onDragOver
и onDrop
атрибуты обработчика событий.
Мы также определили функции для обработки этих событий. Каждая из этих функций-обработчиков получает объект события в качестве аргумента.
Для каждого из обработчиков событий мы вызываем preventDefault()
чтобы браузер не выполнял поведение по умолчанию. Браузер по умолчанию открывает перетащенный файл. Мы также звоним stopPropagation()
чтобы убедиться, что событие не распространяется от дочерних элементов к родительским.
Импортировать DragAndDrop
компонент в App
компонент и визуализировать его под заголовком.
<div className="App">
<h1>React drag-and-drop component</h1>
<DragAndDrop />
</div>
Теперь просмотрите компонент в браузере, и вы должны увидеть что-то вроде изображения ниже.
div
для превращения в зону сброса (большой превью)
Если вы следите за репо, соответствующая ветка 02-start-dragndrop
Управление состоянием с помощью useReducer
Крюк
Нашим следующим шагом будет написание логики для каждого из наших обработчиков событий. Прежде чем мы это сделаем, мы должны подумать, как мы собираемся отслеживать удаленные файлы. Здесь мы начинаем думать об управлении состоянием.
Мы будем отслеживать следующие состояния во время операции перетаскивания:
dropDepth
Это будет целое число. Мы будем использовать его, чтобы отслеживать, на сколько уровней мы находимся в зоне сброса. Позже я объясню это иллюстрацией. (Спасибо Егору Егорову за то, что он пролил на меня свет!)
inDropZone
Это будет логическое значение. Мы будем использовать это, чтобы отслеживать, находимся ли мы внутри зоны сброса или нет.
FileList
Это будет список. Мы будем использовать его для отслеживания файлов, которые были перемещены в зону сброса.
Для обработки состояний React предоставляет useState
и useReducer
крючки. Мы выберем useReducer
ловушку, учитывая, что мы будем иметь дело с ситуациями, когда состояние зависит от предыдущего состояния.
То useReducer
крючок принимает редуктор типа (state, action) => newState
и возвращает текущее состояние в паре с dispatch
метод.
Вы можете прочитать больше о useReducer
в документации React.
Внутри App
компонент (перед return
оператор), добавьте следующий код:
...
const reducer = (state, action) => {
switch (action.type) {
case 'SET_DROP_DEPTH':
return { ...state, dropDepth: action.dropDepth }
case 'SET_IN_DROP_ZONE':
return { ...state, inDropZone: action.inDropZone };
case 'ADD_FILE_TO_LIST':
return { ...state, fileList: state.fileList.concat(action.files) };
default:
return state;
}
};
const [data, dispatch] = React.useReducer(
reducer, { dropDepth: 0, inDropZone: false, fileList: [] }
)
...
То useReducer
крючок принимает два аргумента: редьюсер и начальное состояние. Возвращает текущее состояние и dispatch
функция, с помощью которой можно обновить состояние. Состояние обновляется путем отправки действия, содержащего type
и дополнительная полезная нагрузка. Обновление состояния компонента зависит от того, что возвращается оператором case в результате типа действия. (Обратите внимание, что наше начальное состояние object
.)
Для каждой из переменных состояния мы определили соответствующий оператор case для ее обновления. Обновление выполняется путем вызова dispatch
функция, возвращаемая useReducer
.
Теперь пройти data
и dispatch
в виде props
к DragAndDrop
компонент, который у вас есть в вашем App.js файл:
<DragAndDrop data={data} dispatch={dispatch} />
В верхней части DragAndDrop
компонент, мы можем получить доступ к обоим значениям из props
.
const { data, dispatch } = props;
Если вы следите за репо, соответствующая ветка 03-define-reducers
.
Давайте закончим логику наших обработчиков событий. Обратите внимание, что многоточие представляет собой две строки:
e.preventDefault()
e.stopPropagation()
const handleDragEnter = e => {
...
dispatch({ type: 'SET_DROP_DEPTH', dropDepth: data.dropDepth + 1 });
};
const handleDragLeave = e => {
...
dispatch({ type: 'SET_DROP_DEPTH', dropDepth: data.dropDepth - 1 });
if (data.dropDepth > 0) return
dispatch({ type: 'SET_IN_DROP_ZONE', inDropZone: false })
};
На приведенном ниже рисунке у нас есть вложенные зоны перетаскивания A и B. A — это наша интересующая нас зона. Здесь мы хотим прослушивать события перетаскивания.
Иллюстрация ondragenter
и ondragleave
события (большой предварительный просмотр)
При перетаскивании в зону перетаскивания каждый раз, когда мы сталкиваемся с границей, ondragenter
событие запущено. Это происходит на границах A-in
и B-in
. Так как мы входим в зону, мы увеличиваем dropDepth
.
Аналогично, при перетаскивании из зоны перетаскивания каждый раз, когда мы сталкиваемся с границей, ondragleave
событие запущено. Это происходит на границах A-out
и B-out
. Поскольку мы покидаем зону, мы уменьшаем значение dropDepth
. Обратите внимание, что мы не устанавливаем inDropZone
к false
на границе B-out
. Вот почему у нас есть эта строка для проверки dropDepth и возврата из функции dropDepth
лучше чем 0
.
if (data.dropDepth > 0) return
Это связано с тем, что, хотя ondragleave
событие запущено, мы все еще в зоне A. Только после того, как мы нажмем A-out
, и dropDepth
сейчас 0
что мы установили inDropZone
к false
. На данный момент мы покинули все зоны сброса.
const handleDragOver = e => {
...
e.dataTransfer.dropEffect="copy";
dispatch({ type: 'SET_IN_DROP_ZONE', inDropZone: true });
};
Каждый раз, когда это событие срабатывает, мы устанавливаем inDropZone
к true
. Это говорит нам о том, что мы находимся внутри зоны сброса. Мы также установили dropEffect
на dataTransfer
Возражать copy
. На Mac это приводит к отображению зеленого знака плюса при перетаскивании элемента в зоне перетаскивания.
const handleDrop = e => {
...
let files = [...e.dataTransfer.files];
if (files && files.length > 0) {
const existingFiles = data.fileList.map(f => f.name)
files = files.filter(f => !existingFiles.includes(f.name))
dispatch({ type: 'ADD_FILE_TO_LIST', files });
e.dataTransfer.clearData();
dispatch({ type: 'SET_DROP_DEPTH', dropDepth: 0 });
dispatch({ type: 'SET_IN_DROP_ZONE', inDropZone: false });
}
};
Мы можем получить доступ к удаленным файлам с помощью e.dataTransfer.files
. Значение представляет собой объект, подобный массиву, поэтому мы используем синтаксис распространения массива, чтобы преобразовать его в JavaScript
множество.
Теперь нам нужно проверить, есть ли хотя бы один файл, прежде чем пытаться добавить его в наш массив файлов. Мы также следим за тем, чтобы не включать файлы, которые уже находятся на нашем fileList
. То dataTransfer
объект очищается при подготовке к следующей операции перетаскивания. Мы также сбрасываем значения dropDepth
и inDropZone
.
Обновите className
принадлежащий div
в DragAndDrop
компонент. Это условно изменит className
принадлежащий div
в зависимости от значения data.inDropZone
.
<div className={data.inDropZone ? 'drag-drop-zone inside-drag-area' : 'drag-drop-zone'}
...
>
<p>Drag files here to upload</p>
</div>
Отобразить список файлов в App.js путем сопоставления через data.fileList
.
<div className="App">
<h1>React drag-and-drop component</h1>
<DragAndDrop data={data} dispatch={dispatch} />
<ol className="dropped-files">
{data.fileList.map(f => {
return (
<li key={f.name}>{f.name}</li>
)
})}
</ol>
</div>
Теперь попробуйте перетащить несколько файлов в зону перетаскивания. Вы увидите, что когда мы входим в зону сброса, фон становится менее непрозрачным, потому что inside-drag-area
класс активирован.
Когда вы освободите файлы внутри зоны сброса, вы увидите имена файлов, перечисленные под зоной сброса:
Зона перетаскивания показывает низкую непрозрачность во время перетаскивания (большой предварительный просмотр)
Список файлов, сброшенных в зону перетаскивания (большой превью)
Полная версия этого руководства находится на 04-finish-handlers
филиал.
Вывод
Мы увидели, как обрабатывать загрузку файлов в React с помощью HTML
API перетаскивания. Мы также узнали, как управлять состоянием с помощью useReducer
крюк. Мы могли бы расширить файл handleDrop
функция. Например, мы могли бы добавить еще одну проверку для ограничения размеров файлов, если бы захотели. Это может произойти до или после проверки существующих файлов. Мы также могли бы сделать зону перетаскивания кликабельной, не затрагивая функциональность перетаскивания.
Ресурсы
- «Справочник по API хуков:
useReducer
», Реагировать Документы - «HTML Drag-and-Drop API», веб-документы MDN
- «Примеры веб-разработки и XML-разработки с использованием DOM», веб-документы MDN
- «Как сделать загрузчик файлов с помощью перетаскивания с помощью ванильного JavaScript», Джозеф Циммерман, Smashing Magazine
- «Простая загрузка файлов перетаскиванием в React», Егор Егоров, Medium

(ра, кс, иль)
[ad_2]
Source: https://smashingmagazine.com
Заключение
Вы ознакомились с статьей — Как использовать API перетаскивания HTML в React
Пожалуйста оцените статью, и напишите комментарий.