Mehr als 100 Zeilen Code zur Implementierung von React Drag Hooks

Mehr als 100 Zeilen Code zur Implementierung von React Drag Hooks

Vorwort

Der Quellcode umfasst insgesamt nur mehr als 100 Zeilen. Nachdem Sie dies gelesen haben, können Sie die Implementierungsideen einiger ausgereifter React-Drag-Bibliotheken wie react-dnd grob verstehen und dann sehr schnell mit diesen Bibliotheken beginnen.

Die Verwendung von Hooks hat im Allgemeinen folgende Auswirkungen:

Unser Ziel ist die Implementierung eines useDrag- und useDrop-Hooks, mit dem sich Elemente problemlos ziehen lassen. In jedem Lebenszyklus des Ziehens können Sie, wie unten gezeigt, die Nachrichtenübermittlung anpassen (und dabei nebenbei mehrere Ereignisse einführen, die durch das Ziehen ausgelöst werden).

  • dragstart: Wenn der Benutzer mit dem Ziehen beginnt, wird es am gezogenen Knoten ausgelöst. Das Zielattribut dieses Ereignisses ist der gezogene Knoten.
  • dragenter: Beim Ziehen in den aktuellen Knoten wird es einmal auf dem aktuellen Knoten ausgelöst und das Zielattribut des Ereignisses ist der aktuelle Knoten. Normalerweise sollten Sie in der Abhörfunktion dieses Ereignisses angeben, ob das Ablegen der gezogenen Daten auf dem aktuellen Knoten zulässig sein soll. Wenn der aktuelle Knoten keine Listener-Funktion für das Ereignis hat oder die Listener-Funktion keine Operation ausführt, bedeutet dies, dass am aktuellen Knoten keine Daten gelöscht werden dürfen. Die optische Anzeige des Ziehens in den aktuellen Knoten wird ebenfalls in der Abhörfunktion dieses Ereignisses eingestellt.
  • Dragover: Wenn es über den aktuellen Knoten gezogen wird, wird es kontinuierlich auf dem aktuellen Knoten ausgelöst (alle paar hundert Millisekunden), und das Zielattribut des Ereignisses ist der aktuelle Knoten. Der Unterschied zwischen diesem Ereignis und dem Dragenter-Ereignis besteht darin, dass das Dragenter-Ereignis beim Betreten des Knotens ausgelöst wird und das Dragover-Ereignis dann weiterhin ausgelöst wird, solange der Knoten nicht verlassen wird.
  • dragleave: Wenn die Drag-Operation den aktuellen Knotenbereich verlässt, wird sie auf dem aktuellen Knoten ausgelöst. Das Zielattribut dieses Ereignisses ist der aktuelle Knoten. Wenn Sie die Drag & Drop-Operation auf dem aktuellen Knoten visuell anzeigen möchten, legen Sie sie in der Listener-Funktion dieses Ereignisses fest.

Verwendung + Erklärung des Quellcodes

Klasse Hello erweitert React.Component<any, any> {
 Konstruktor(Requisiten: beliebig) {
  super(Requisiten)
  dieser.Zustand = {}
 }

 rendern() {
  zurückkehren (
   <Ziehen und Ablegen>
    <DragElement />
    <DropElement />
   </DragAndDrop>
  )
 }
}

ReactDOM.render(<Hallo />, window.document.getElementById("root"))

Wie oben erwähnt, besteht die Funktion der DragAndDrop-Komponente darin, Nachrichten an alle Komponenten weiterzugeben, die useDrag und useDrop verwenden, z. B. welcher DOM das aktuell gezogene Element ist, oder Sie können bei Bedarf andere Informationen hinzufügen. Schauen wir uns die Implementierung an.

const DragAndDropContext = React.createContext({ DragAndDropManager: {} });
const DragAndDrop = ({ untergeordnete Elemente }) => (
 <DragAndDropContext.Provider-Wert={{ DragAndDropManager: neuer DragAndDropManager() }}>
  {Kinder}
 </DragAndDropContext.Provider>
)

Sie können sehen, dass die Nachrichtenübermittlung mithilfe der Context API von React implementiert wird. Der Fokus liegt auf diesem DragAndDropManager. Schauen wir uns die Implementierung an.

exportiere Standardklasse DragAndDropManager {

 Konstruktor() {
  this.active = null
  diese.abonnements = []
  diese.id = -1
 }

 setActive(activeProps) {
  dies.active = activeProps
  this.subscriptions.forEach((Abonnement) => Abonnement.Rückruf())
 }

 abonnieren(Rückruf) {
  diese.id += 1
  dies.abonnements.push({
   Rückruf,
   ID: diese.ID,
  })

  gib diese.id zurück
 }

 Abbestellen(ID) {
  diese.Abonnements = diese.Abonnements.Filter((sub) => sub.id !== id)
 }
}

Die Funktion von setActive besteht darin, aufzuzeichnen, welches Element gerade gezogen wird. Sie wird in useDrag verwendet. Wenn wir uns die Implementierung der useDrag-Hooks ansehen, werden wir verstehen, dass wir wissen, welches Element gerade gezogen wird, solange wir die setActive-Methode aufrufen und das gezogene DOM-Element an sie übergeben.

Darüber hinaus habe ich auch eine API zum Abonnieren von Ereignissen hinzugefügt, „subscribe“. Ich habe sie noch nicht verwendet, daher können Sie sie in diesem Beispiel ignorieren. Sie müssen nur wissen, dass Sie Abonnementereignisse hinzufügen können.

Als nächstes schauen wir uns die Verwendung von useDrag an. Die Implementierung von DragElement ist wie folgt:

Funktion DragElement() {
 Konstante Eingabe = useRef(null)
 const hanleDrag = useDrag({
  ref: Eingabe,
  Sammlung: {}, // Sie können hier jede Nachricht eingeben, die Sie an das Drop-Element übergeben möchten. Diese wird später als Parameter an das Drop-Element übergeben})
 zurückkehren (
  <div ref={Eingabe}>
   <h1 Rolle="Schaltfläche" beiKlick={handleDrag}>
    Drag-Element
  </div>
 )
}

Schauen wir uns die Implementierung von useDrag an, die sehr einfach ist

exportiere Standardfunktion useDrag(props) {

 const { DragAndDropManager } = useContext(DragAndDropContext)
 
 const handleDragStart = (e) => {
  DragAndDropManager.setActive(Eigenschaften.Sammlung)
  wenn (e.dataTransfer !== undefiniert) {
   e.dataTransfer.effectAllowed = "verschieben"
   e.dataTransfer.dropEffect = "verschieben"
   e.dataTransfer.setData("text/plain", "drag") // Firefox-Fix
  }
  wenn (props.onDragStart) {
   props.onDragStart(DragAndDropManager.active)
  }
 }
 
 useEffect(() => {
  wenn (!props.ref) return () => {}
  Konstante {
   ref: { aktuell },
  } = Requisiten
  wenn (aktuell) {
   current.setAttribute("ziehbar", true)
   aktuell.addEventListener("dragstart", handleDragStart)
  }
  zurückgeben () => {
   aktuell.removeEventListener("dragstart", handleDragStart)
  }
 }, [Eigenschaften.ref.aktuell])

 RückgabegriffDragStart
}

Was useDrag macht, ist sehr einfach.

  • Verwenden Sie zunächst useContext, um die Daten des äußersten Speichers abzurufen. Im obigen Code handelt es sich dabei um den DragAndDropManager.
  • Wenn in useEffect ein Ref von außen übergeben wird, wird das Draggable-Attribut des DOM-Elements auf „true“ gesetzt, was bedeutet, dass es gezogen werden kann.
  • Binden Sie dann das Dragstart-Ereignis an dieses Element. Beachten Sie, dass wir das Ereignis entfernen müssen, wenn wir die Komponente zerstören, um Speicherlecks zu vermeiden.
  • Das Ereignis handleDragStart aktualisiert zuerst die von außen an unseren externen Speicher übergebene props.collection, sodass jedes zu ziehende Element die in unserem useDrag übergebenen useDrag({collection: {}})-Informationen über DragAndDropManager.setActive(props.collection) an den externen Speicher übergeben kann.
  • Als nächstes machen wir etwas mit dem dataTransder-Attribut, um das Drag-Attribut des Elements auf Verschieben zu setzen und es mit Firefox kompatibel zu machen.
  • Schließlich wird immer, wenn ein Drag-Ereignis ausgelöst wird, auch das onDragStart-Ereignis von der Außenwelt ausgelöst und wir übergeben die Daten im Store dorthin.

Darunter sind die Verwendung von useDrop und die Implementierung von DropElement wie folgt:

Funktion DropElement(Eigenschaften: beliebig): beliebig {
 Konstante Eingabe = useRef(null)
 verwendenDrop({
  ref: Eingabe,
  // e stellt das Ereignisobjekt des Elements dar, über das gezogen wird, wenn das Ereignis „dragOver“ auftritt // „collection“ sind die im Store gespeicherten Daten // „showAfter“ gibt an, ob die Maus über das abgelegte Element fährt, wenn sie das Element zieht (oben ist die obere Hälfte, unten ist die untere Hälfte)
  onDragOver: (e, Sammlung, ShowAfter) => {
  // Wenn es die obere Hälfte passiert, wird die obere Grenze des Drop-Elements rot, if (!showAfter) {
    input.current.style = "border-unten: keine;border-oben: 1px durchgehend rot"
   } anders {
    // Wenn es die untere Hälfte passiert, ist der obere Rand des Drop-Elements rot. input.current.style = "border-top: none; border-bottom: 1px solid red"
   }
  },
  // Wenn Sie die Maus über dem Drop-Element loslassen, wird der Stil gelöscht onDrop: () => {
   Eingabe.aktueller.Stil = ""
  },
  // Wenn Sie das Drop-Element verlassen, wird der Stil gelöscht onDragLeave: () => {
   Eingabe.aktueller.Stil = ""
  },
 })
 zurückkehren (
  <div>
   <h1 ref={input}>Element löschen</h1>
  </div>
 )
}

Schauen wir uns abschließend die Implementierung von useDrop an.

exportiere Standardfunktion useDrop(props) {
// Daten im äußersten Speicher abrufen const { DragAndDropManager } = useContext(DragAndDropContext)
 const handleDragOver = (e) => {
 // e ist das Drag-Event-Objekt e.preventDefault()
  // Siehe das Diagramm von getBoundingClientRect unten const overElementHeight = e.currentTarget.getBoundingClientRect().height / 2
  const overElementTopOffset = e.currentTarget.getBoundingClientRect().top
  // clientY ist der Abstand von der Maus zum oberen Rand des sichtbaren Bereichs der Browserseite const mousePositionY = e.clientY
  // mousePositionY - overElementTopOffset ist der Abstand von der Maus innerhalb des Elements zum oberen Rand des Elements const showAfter = mousePositionY - overElementTopOffset > overElementHeight
  wenn (props.onDragOver) {
   props.onDragOver(e, DragAndDropManager.active, showAfter)
  }
 }
 // Drop-Ereignis const handledDop = (e: React.DragEvent) => {
  e.preventDefault()

  wenn (props.onDrop) {
   props.onDrop(DragAndDropManager.active)
  }
 }
 // dragLeave-Ereignis const handledragLeave = (e: React.DragEvent) => {
  e.preventDefault()

  wenn (props.onDragLeave) {
   props.onDragLeave(DragAndDropManager.active)
  }
 }
  // Ereignisse registrieren. Beachten Sie, dass Sie Ereignisse deregistrieren sollten, wenn Sie Komponenten zerstören, um Speicherlecks zu vermeiden. useEffect(() => {
  wenn (!props.ref) return () => {}
  Konstante {
   ref: { aktuell },
  } = Requisiten
  wenn (aktuell) {
   aktuell.addEventListener("dragover", handleDragOver)
   aktuell.addEventListener("drop", behandeltDop)
   current.addEventListener("dragleave", handledragLeave)
  }
  zurückgeben () => {
   aktuell.removeEventListener("dragover", handleDragOver)
   aktuell.removeEventListener("drop", behandeltDop)
   aktuell.removeEventListener("dragleave", handledragLeave)
  }
 }, [Eigenschaften.ref.aktuell])
}

GetBoundingClientRect API-Diagramm:

rectObject = Objekt.getBoundingClientRect();

rectObject.top: der Abstand von der Oberseite des Elements zur Oberseite des Fensters;

rectObject.right: der Abstand von der rechten Seite des Elements zur linken Seite des Fensters;

rectObject.bottom: der Abstand von der Unterseite des Elements zur Oberseite des Fensters;

rectObject.left: der Abstand von der linken Seite des Elements zur linken Seite des Fensters;

Damit ist dieser Artikel über die Implementierung von React Drag-and-Drop-Hooks mit mehr als 100 Codezeilen abgeschlossen. Weitere relevante Inhalte zu React Drag-and-Drop-Hooks finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung des verschiebbaren und bearbeitbaren Gantt-Diagramms (Highcharts können für Vue und React verwendet werden)
  • Typescript+React zum Erzielen einfacher Drag-and-Drop-Effekte auf Mobilgeräten und PCs
  • react-beautiful-dnd implementiert die Drag-and-Drop-Funktion für Komponenten
  • Verwenden von react-beautiful-dnd zum Implementieren von Drag & Drop zwischen Listen
  • React.js-Komponente implementiert Drag & Drop-Sortierkomponentenfunktionsprozessanalyse
  • Reagieren Sie mit Beispielcode zur Implementierung der Drag & Drop-Funktion
  • React.js-Komponente implementiert Drag-and-Drop-Kopie und sortierbaren Beispielcode
  • Lassen Sie uns noch einmal über eine Reihe von Problemen sprechen, die durch die Implementierung nativer JS-Drag-Effekte in React.js verursacht werden
  • Gedanken zur Implementierung nativer JS-Drag-Effekte basierend auf React.js
  • React implementiert einfache Drag & Drop-Funktion

<<:  Sortierung der technischen Hinweise zum Linux-Kernel-Gerätetreiber-Kernel-Debugging

>>:  So ändern Sie das Anfangskennwort eines Benutzers in mysql5.7

Artikel empfehlen

Neue Blockbereichsfunktion von JavaScript ES

Inhaltsverzeichnis 1. Was ist Blockbereich? 2. Wa...

So zeichnen Sie in CocosCreator ein cooles Radardiagramm

Inhaltsverzeichnis Vorwort Vorschau Text Grafikko...

Grundlegende Verwendung des Befehls wget unter Linux

Inhaltsverzeichnis Vorwort 1. Laden Sie eine einz...

...

So schreiben Sie eleganten JS-Code

Inhaltsverzeichnis Variable Verwenden Sie aussage...

Lösung für falsche Zeichenfolgenwerte in MySQL

Viele Freunde berichten von folgendem Fehler, wen...

Vue implementiert Klick-Feedback-Anweisungen für den Wasserwelleneffekt

Inhaltsverzeichnis Wasserwelleneffekt Sehen wir u...

Erfahren Sie, wie Sie ein Vue-Projekt mit Docker bereitstellen

1.Schreiben Sie davor: Als leichtgewichtige Virtu...

Warum Google und Facebook Docker nicht verwenden

Der Grund für das Schreiben dieses Artikels beste...

So installieren und verwenden Sie Server-U Version 14

Einführung der Server-U-Software Server-U ist ein...

Eine kurze Diskussion zum CSS-Höhenkollapsproblem

Leistung Zum Beispiel: HTML: <div Klasse="...

Empfehlen Sie 60 Paging-Fälle und bewährte Vorgehensweisen

<br />Struktur und Hierarchie reduzieren die...

VUE implementiert einen Beispielcode für das Spiel Flappy Bird

Flappy Bird ist ein sehr einfaches kleines Spiel,...