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

echars 3D-Kartenlösung für benutzerdefinierte Farben von Regionen

Inhaltsverzeichnis Frage verlängern Lösung des Pr...

Beispiel für die CSS3-Clear-Float-Methode

1. Zweck Durch diesen Artikel kann jeder die Prin...

Beispiele für JavaScript-Entschüttelungen und Drosselung

Inhaltsverzeichnis Stabilisierung Drosselung: Ant...

Einführung in die Verwendung des HTML-Basistags target=_parent

Der <base>-Tag gibt die Standardadresse oder...

Die beste Erklärung zu HTTPS

Guten Morgen allerseits, ich habe meinen Artikel ...

Natives JS zum Erzielen eines Schiebeknopfeffekts

Der spezifische Code des mit Js erstellten Schieb...

Implementieren einer benutzerdefinierten Bildlaufleiste mit nativem JS

In diesem Artikelbeispiel wird der spezifische JS...

10 Tipps zur Verbesserung der Website-Benutzerfreundlichkeit

Ob Unternehmenswebsite, persönlicher Blog, Shoppi...

jQuery implementiert dynamische Tag-Ereignisse

In diesem Artikel wird der spezifische Code von j...

MySQL-Datenbank implementiert MMM-Hochverfügbarkeitsclusterarchitektur

Konzept MMM (Master-Master-Replikationsmanager fü...

XHTML-Tags haben ein schließendes Tag

<br />Ursprünglicher Link: http://www.dudo.o...

Detaillierte Erklärung der Datentypen und Schemaoptimierung in MySQL

Ich lerne derzeit etwas über MySQL-Optimierung. D...