React.js: implemente la función de arrastrar y soltar sin usar bibliotecas externas

Conozca los detalles de la implementación de funciones de arrastrar y soltar en React desde cero.

Primero veamos el resultado de lo que estaremos construyendo. Estoy probando .gif, espero que funcione en todas partes como se esperaba. He usado Camtasia con una licencia personal.

Los puntos clave de aprendizaje son:

  1. hacer que un elemento se pueda arrastrar agregando el atributo "arrastrable"
  2. hacer que un área se pueda soltar implementando el evento "dragover"
  3. capturar los datos de arrastre implementando el evento "dragstart"
  4. capturar la gota implementando el evento "gota"
  5. Implementar el evento "arrastrar" que se dispara mientras se arrastra el elemento.
  6. almacenar los datos intermedios en el objeto dataTransfer

Para los aprendices visuales, diríjase al video a continuación.

Paso 1: cree la aplicación raíz para la demostración

Todo el código para arrastrar y soltar irá al componente AppDragDropDemo.js.

import React from 'react';import ReactDOM from 'react-dom';import '.index.css';import AppDragDropDemo from './AppDragDropDemo';
ReactDOM.render(, document.getElementById("root"));

El punto de entrada para AppDragDropDemo se parece al código siguiente.

import React, { Component } from 'react';
export default class AppDragDropDemo extends Component { render () { return ( DRAG & DROP DEMO ); }}

Si ahora ejecuta la aplicación, se le presentará esta impresionante pantalla (juego de palabras)

Paso 2: crea el objeto de estado para almacenar algunas tareas

Creemos algunas tareas para simular una aplicación simple. Lo que intentamos hacer es arrastrar y soltar estas tareas en diferentes categorías, como wip, completey así sucesivamente.

export default class AppDragDropDemo extends Component { state = { tasks: [{name:"Learn Angular", category:"wip", bgcolor: "yellow"}, {name:"React", category:"wip", bgcolor:"pink"}, {name:"Vue", category:"complete", bgcolor:"skyblue"} ]}
 render () { return ( DRAG & DROP DEMO ); }}

Paso 3: organiza nuestros datos en categorías

Implementemos el siguiente código en el método de representación, para agrupar las tareas en sus respectivas categorías wipy complete. Siéntase libre de agregar más categorías y jugar con el código.

Puede copiar y pegar el código de arriba del fragmento de abajo.

render() { var tasks = { wip: [], complete: [] } this.state.tasks.forEach ((t) => { tasks[t.category].push( this.onDragStart(e, t.name)} draggable className="draggable" style={{backgroundColor: t.bgcolor}}> {t.name} ); });

En el código anterior, estamos recorriendo todas las tareas y creando un div para cada elemento de la tarea y almacenándolo en las categorías respectivas.

Por lo tanto, wip[]contiene todas las tareas en la categoría wip y complete[]contiene todas las tareas completadas.

Paso 4: haga que el elemento de la tarea se pueda arrastrar

Agregue el atributo arrastrable a o cualquier elemento para hacer que un elemento se pueda arrastrar. Consulte el bloque de código anterior para conocer el formato de texto del código.

Paso 5: crea un contenedor desplegable

Para crear un contenedor desplegable, implemente dragover event. Ahora, dado que queremos deshabilitar el evento dragover predeterminado, simplemente llamamos al event.preventDefault()desde el evento dragover.

También renderizaremos {tasks.wip}y {tasks.complete}en sus correspondientes elementos div.

return ( 

DRAG & DROP DEMO

this.onDragOver(e)} onDrop={(e)=>{this.onDrop(e, "wip")}}> WIP {tasks.wip} this.onDragOver(e)} onDrop={(e)=>this.onDrop(e, "complete")}> COMPLETED {tasks.complete} );
Let us now implement the onDragOver() event handler.

La salida hasta ahora se verá como la siguiente figura.

Paso 6: captura el estado del elemento que se arrastra

Modifiquemos el código donde estamos creando la categoría para cada tarea. Agregue un manejador de eventos ondragstarty pase la identificación / nombre o cualquier información que necesite para persistir mientras se realiza el arrastrar / soltar.

Lo estoy usando namecomo valor único para identificar la tarea. Siéntase libre de usar ID o cualquier clave única que tenga.

Implementemos ahora el onDragStartcontrolador de eventos.

En el controlador onDragStart, tomamos el parámetro y lo almacenamos dentro del objeto dataTransfer. (No se confunda con el nombre de los parámetros, ya que supongo que estaba en un mundo de nombres diferente mientras codificaba esto :).)

Nota de IE : es posible que esto no funcione con IE. Para IE, la mejor práctica es dar el formato como clave como se muestra a continuación.

Instead of
ev.dataTransfer.setData("id", id)
USE
ev.dataTransfer.setData(“text/plain”,id)

The above handler will ensure that the element being dragged is stored in the event object and is available for use when required. It may be required while dropping on a target.

Now if you run the application and drag the elements, the following logs will be output.

Step 7 — handle the drop event.

Let’s open up the render method and add the onDrop event to the div with a className of droppable.

In the above code, we add the drop event handler, and pass the required category complete as an argument. This indicates we are dropping the element from the wip state to the complete state (category). Please feel free to change the names, as required.

Let’s now implement the onDrop() event handler.

Here’s the code you can copy/paste:

onDrop = (ev, cat) => { let id = ev.dataTransfer.getData("id"); let tasks = this.state.tasks.filter((task) => { if (task.name == id) { task.category = cat; } return task; }); this.setState({ ...this.state, tasks }); }

In the onDrop event handler, we grab the task being dragged by using getData method on the event’s dataTransfer object.

We then create a new tasks array by using the filter method, and change the category of the task being dragged.

setState() will trigger render, and the tasks will be rendered in the right areas.

IE note: To make it work in IE, use the below getData method.

Instead of

var id = ev.dataTransfer.getData(“id”)

use

var id = ev.dataTransfer.getData(“text”)

Step 8 — to implement drop from “complete” to “wip,” add the onDrop handler

The onDrop() handler remains the same as earlier.

Finally, run the code and marvel at your creation :) and have fun while coding.

You can grab the source code from here.

Note: for this to work cross browser, change the setData type to string.

for example, to set data, use ev.dataTransfer.setData(“text/plain”,id). To read data, use var id = ev.dataTransfer.getData(“text”)

Since my aim was to demonstrate the core drag and drop features, the code has not been optimized for factors such as design and naming conventions.

Learn with me @Learner + Fullstack Coach (@rajeshpillai): //twitter.com/rajeshpillai

Promotion: Special 10$ coupon for Medium readers for my upcoming live ReactJS-Beyond the basics course on Udemy in case you wish to support our open source curriculum Mastering frontend engineering in 12 to 20 weeks.

Just published my early access course Javascript Deep Dive — Code your own React