Vue implementiert einen visuellen Drag-Page-Editor

Vue implementiert einen visuellen Drag-Page-Editor

Online-Adresse (die Verwendung eines VPN ist schneller)

Ein visueller Seiteneditor klingt unerreichbar, oder? Schauen wir uns zuerst das animierte Bild an!

Bevor ich diese Funktion implementierte, habe ich im Internet viele Informationen eingeholt, aber letztlich nichts gefunden. In all den verschiedenen Artikeln wurde von meinem früheren Ich gesprochen!

Sie müssen also jetzt selbst herausfinden, wie Sie das erreichen.

Zu berücksichtigende Punkte:

  • Drag & Drop-Implementierung
  • Definition der Datenstruktur
  • Aufteilung der Komponenten
  • Wartbarkeit und Skalierbarkeit

Objektreferenz: Das ist der coolste Trick, den ich je gesehen habe. Lassen Sie mich die Details einzeln erklären! !

Drag & Drop-Implementierung

Ziehen von Ereignissen

Hier wird das Drag-Ereignis von H5 verwendet, hauptsächlich für:

dragstart // Wird ausgelöst, wenn Sie mit dem Ziehen eines Elements beginnen draggable // Geben Sie das ziehbare Element an dragend // Wird ausgelöst, wenn der Ziehvorgang beendet ist dragover // Wird ausgelöst, wenn das gezogene Element über ein ablegbares Ziel bewegt wird drop // Wird ausgelöst, wenn das gezogene Element auf einem ablegbaren Ziel losgelassen wird

Sehen wir uns an, wie diese Ereignisse verwendet werden:

<!-- Daten aus der Elementliste ziehen-->
<Skript>
// com ist die entsprechende Ansichtskomponente und typeList wird im Release-Bereich angezeigt: {
 Banner:
  Name: 'Karussell',
  Symbol: „el-icon-picture“,
  com: Banner
 },
 Produkt: {
  Name: "Produkt",
  Symbol: „el-icon-s-goods“,
  com: Produkt
 },
 Bilder:
  Name: 'Bild',
  Symbol: „el-icon-picture“,
  com: Bilder
 },
}
</Skript>
<!-- Element ziehen -->
<ul 
 @dragstart="ziehenStarten"
 @dragend="ziehenEnde"
>
 <li 
  v-for="(Wert, Schlüssel, Index) in Typliste"
  verschiebbar 
  :Datentyp="Schlüssel"
  :Schlüssel="Index + 1"
 >
  <span:class="val.icon"></span>
  <p>{{val.name}}</p>
 </li>
</ul>
<!-- Freigabebereich -->
<div 
 Klasse="Inhalt anzeigen"
 @drop="Droge"
 @dragover="Überziehen"
>
</div>

Ziehen zum Starten

Definieren Sie einen Variablentyp, um den Typ des aktuell gezogenen Elements zu bestimmen, wenn das Ziehereignis beginnt, z. B. Produkt, Werbebild usw.

// Ziehen Sie den Typ dragStart(e) {
 dieser.Typ = e.Ziel.Datensatz.Typ
}

Nach der Bestimmung des Typs gelangen Sie zum nächsten Schritt des Freigabebereichs

Bewegung in der Release-Zone

Während des Bewegungsvorgangs muss die Position des gezogenen Elements in Echtzeit entsprechend der Mausposition berechnet werden. Sie können nach unten scrollen, um eine Vorschau des animierten Effekts anzuzeigen!

// 'view-content': die Klasse der äußeren Box, direkt pushen
// 'item': das Element innerhalb der Box, die Position muss berechnet und die Transformationsoperation muss durchgeführt werden dragOver() {
 let Klassenname = e.Ziel.Klassenname
 let name = Klassenname !== 'Inhalt anzeigen' ? 'Element' : 'Inhalt anzeigen'

 // Standarddaten der Komponente const defaultData = {
  Typ: dieser.Typ, // Komponententyp Status: 2, // Standardstatus Daten: [], // Basisdaten Optionen: {} // andere Operationen }

 if (name == 'Inhalt anzeigen') {
  //...
 } sonst wenn (Name == 'Artikel') {
  //...
 }
}

Randbearbeitung, Winkelberechnung

Kernvariablen:

  • isPush: Gibt an, ob das gezogene Element in die Seitendaten geschoben wurde
  • index: der endgültige Indexwert des gezogenen Elements
  • curIndex: Der Indexwert des Elements, in dem sich die Maus befindet
  • Richtung: der obere/untere Teil des Elements, in dem sich die Maus befindet

Wenn name=='view-content' , bedeutet dies, dass sich das Drag-Element im äußeren und leeren freigebbaren Bereich befindet. Wenn es nicht hinzugefügt wird, schieben Sie es einfach direkt.

if (name == 'Inhalt anzeigen') {
 wenn (!this.isPush) {
  dieser.index = diese.ansicht.länge
  this.isPush = true
  diese.view.push(Standarddaten)
 }
}

Wenn name=='item', also über einem bestehenden Element, müssen Sie die Position berechnen, nach oben/unten, hinzufügen oder verschieben

wenn (Name == 'Artikel') {
 lass Ziel = e.Ziel
 lass [y, h, aktuellerIndex] = [e.OffsetY, Ziel.OffsetHeight, Ziel.Dataset.Index]
 let direction = y < (h / 2) // Berechne die Position der Maus auf dem aktuellen Element, um die Auf-/Ab-Richtung des gezogenen Elements zu bestimmen if (!this.isPush) {
  // Erste
  wenn (Richtung) {
   wenn (aktuellerIndex == 0) {
    diese.Ansicht.unshift(Standarddaten)
   } anders {
    this.view.splice(aktuellerIndex, 0, Standarddaten)
   }
  } anders {
   aktuellerIndex = +aktuellerIndex + 1
   this.view.splice(aktuellerIndex, 0, Standarddaten)
  }
 } anders {
  //Umzug
  wenn (Richtung) {
   var i = aktuellerIndex == 0 ? 0 : aktuellerIndex - 1
   var Ergebnis = diese.Ansicht[i]['status'] == 2
  } anders {
   var i = +aktuellerIndex + 1
   var Ergebnis = this.view.length > i && this.view[i]['status'] == 2
  }
  
  // Ob das gezogene Element seine Position ändern muss, wenn (Ergebnis) return

  const temp = diese.view.splice(diesen.index, 1)
  this.view.splice(aktuellerIndex, 0, temp[0])
 }
 this.index = curIndex // Elementposition ziehen this.isPush = true // Bei Eingabe drücken, das ist wahr
}
  • first: Wenn nicht gedrückt, wird die Position des gezogenen Elements basierend auf dem aktuellen Index und der aktuellen Richtung bestimmt
  • Verschieben: Push- und Bewegungszustand. Suchen Sie den Zustand des entsprechenden Werts entsprechend dem aktuellen Index und der aktuellen Richtung. Wenn es sich um ein gezogenes Element handelt, geben Sie es zurück, andernfalls ändern Sie die Position.

Zusammenfassend: Holen Sie sich den Index des Elements, auf dem sich die Maus derzeit befindet, und berechnen Sie dann, ob sich die Maus in der oberen oder unteren Hälfte des Elements befindet, um auf die Position des gezogenen Elements zu schließen! ! !

Kleine Frage:

Im obigen name=='item' muss das Event-Ereignis das Standardereignis blockieren, um zu vermeiden, dass das Ziel ein inneres Element ist, was die Berechnung der Position unmöglich macht. Allerdings funktioniert die alleinige Verwendung der Ereignisblockierung hier nicht. Ich weiß nicht, warum. Alle untergeordneten Elemente von .item müssen mit dem Attribut pointer-events: none! hinzugefügt werden.

e.preventDefault()
e.stopPropagation()

.item div{
 Zeigerereignisse: keine;
}

Enden ziehen

Sobald Sie die Maus loslassen oder den Freigabebereich verlassen, wird der Ausgangszustand wiederhergestellt.

Welche Rolle spielt der Status hier?

  1. Um zu bestimmen, ob es sich bei einem Element um ein Drag-Element handelt, werden die oben genannten Berechnungsregeln verwendet.
  2. Der Seitenanzeigemodus: Beim Ziehen wird nur der Komponentenname angezeigt, nach dem Loslassen wird der normale Anzeigeinhalt wiederhergestellt.
// Ziehen beenden dragEnd(e) {
 dies.$löschen(diese.ansicht[diesen.index], 'status')
 this.isPush = false
 dieser.Typ = null
},
// Bereits an der angegebenen Position platziert drog(e) {
 e.preventDefault()
 e.stopPropagation()
 dies.dragEnd()
},

Implementierung von Drag & Drop für Inhaltsblöcke

Aus Zeitgründen bin ich hier faul und verwende ein perfekteres Listen-Drag-Plugin Vue.Draggable (Sterne 14,2k)

Nachdem ich es eine Weile studiert hatte, stellte ich fest, dass seine Logik mit dem oben implementierten Drag & Drop zusammenhängt und die spezifischen Implementierungsmethoden ähnlich sind. Ich glaube, dass Sie es mit den obigen praktischen Beispielen auch tun können!

Wie wäre es, wenn Sie es selbst versuchen?

Sie können eine Drag-Komponente basierend auf der Verwendung von Vue.Draggable implementieren, die Operationen wie (Drag, Slot, DOM) verwendet.

(Ich werde später zurückkommen und eines verpacken, wenn ich Zeit habe)

Komponentenabteilung

Die Ansichtskomponente in der Mitte und die Bearbeitungskomponente auf der rechten Seite sind ein Satz von Komponenten. Wie erwartet sind sie ein Satz von Komponenten. Sie sind es wert, ein Satz von Komponenten zu sein!

page=>index verwaltet den Inhalt der gesamten Seite

.
├── Komponenten
| ├── Bearbeiten ## Rechts bearbeiten| | ├── Info # Basisinformationen| | ├── Bild # Werbebild| | ├── Produkt # Produkt| | └── Index # Bauteilinformationen verwalten und bearbeiten| └── Ansicht ## Mittlere Ansicht| | ├── Banner # Slideshow| | ├── Bilder # Werbebild| | └── Produkt # Produktliste└── Seite
 └── index ## Hauptseite

Um den Seitenvorschaueffekt zu erzielen, verwenden Sie einfach die Komponenten unter Komponenten=>Ansicht. Die Verwendung ist dieselbe wie bei Seite=>Index, es sind also keine übermäßigen Änderungen erforderlich!

Definition der Datenstruktur

Um eine übersichtliche und erweiterbare Funktion zu realisieren, ist die Definition einer geeigneten Datenstruktur unabdingbar! Gleichzeitig kann es auch die Qualität Ihres Codes bestimmen!

Natürlich kommt es dabei immer noch auf dein Lernmaterial und dein logisches Denken an!

Die auffälligste Verarbeitungsmethode besteht hierbei darin, die Beziehung zwischen Objekten zu verwenden, sodass für die Wertübertragung zwischen Komponenten nur eine Einwegübertragung erforderlich ist!

Sicht: [
 {
  Typ: "Info",
  Titel: 'Seitentitel',
  Bemerkungen: 'Seitenbemerkungen',
  Hintergrundfarbe: „rot“
 },
 {
  Typ: "Banner",
  Daten: [
   { url: '1.jpg', name: 'Karussellbild 1', link: 'https://karussellbild-sprungadresse.cn' },
   { url: '2.jpg', Name: 'Karussell 2', Link: 'https://carousel jump address.cn' }
  ]
 },
 {
  Typ: "Bilder",
  Daten: [
   { url: '1.jpg', name: 'Werbebild 1', link: 'https://werbebild sprungadresse.cn' },
   { url: '2.jpg', name: 'Werbebild 2', link: 'https://werbebild sprungadresse.cn' }
  ]
 },
 {
  Typ: "Produkt",
  Daten: [
   { id: '1', name: 'Produkt 1', image: '1.jpg' }, 
   { id: '2', name: 'Produkt 2', image: '2.jpg' }
  ],
  Optionen:
   originalPrice: true, // durchgestrichener Preis goodRatio: true, // positive Bewertung volumeStr: false, // Verkaufsmenge}
 }
]

Es ist ein Array und das Element im Array stellt ein Modul dar

  • Typ: Modultyp
  • Daten: Basisinformationen
  • Optionen: andere Operationen

....Sie können auf die ursprünglichen Komponentenmodule zurückgreifen und diese entsprechend Ihren Anforderungen erweitern.

Komponentenwert bearbeiten

Übergeben Sie bei der Auswahl der Ansichtskomponente das in der Ansicht angegebene Artikelobjekt als Parameter an die Bearbeitungskomponente!

Die Objekte zeigen auf die gleiche Speicheradresse und es besteht eine Referenzbeziehung. Sie müssen sie nur einmal ändern, um eine vielschichtige Datenaktualisierung zu erreichen!

<Abschnitt Klasse="r">
 <EditForm
  :data="Requisiten"
  v-if="istRichtig"
 ></EditForm>
</Abschnitt>
<Skript>
// Ansichtskomponente wechseln selectType(index) {
 dies.istRechts = false
 diese.Eigenschaften = diese.Ansicht[index]
 dies.$nextTick(() => dies.isRight = true)
}
</Skript>

Bild-Upload

Oben gibt es zufällig eine Komponente zum Hochladen von Bildern. Ich möchte hier also meine Tipps zur Verwendung mit Ihnen teilen! !

Freunde, die die integrierte Upload-Komponente von Element-ui verwenden, schauen Sie bitte vorbei (klopfen Sie an die Tafel).

Lassen Sie uns zunächst eine vereinfachte Version implementieren:

<!-- Alle Standardmethoden deaktivieren -->
<el-hochladen
 :http-request="hochladen"
 :Dateiliste anzeigen="false"
 mehrere
 Aktion
>
 <img :src="item.url" v-for="(item, index) in Liste" :key="index">
</el-upload>
<Skript>
hochladen(Parameter) {
 const Datei = Parameter.Datei;
 const form = neue FormData();
 form.append("Datei", Datei);
 form.append("clientType", "multipart/formulardaten");

 const index = this.imageIndex // Den Bildindex bearbeiten const data = { 
  url: URL.createObjectURL(Datei), 
  bilden
 }
 wenn (index !== null) {
  // this.list => Bildersammlung this.$set(this.list, index, data)
 } anders {
  diese.Liste.push(Daten)
 }
}
</Skript>
  • Schreiben Sie die Upload-Methode neu
  • Verwenden Sie URL.createObjectURL(file), um eine lokale Vorschauadresse zu erstellen
  • Speichern Sie das Formularobjekt und laden Sie es beim Absenden hoch
// Verwenden Sie gemäß dem obigen Code Promise, um die Upload-Funktion zu implementieren const request = []
diese.Liste.fürJeden(Element => {
 Anfrage.push(
  neues Versprechen((lösen, ablehnen) => {
   /**
    * Upload-Schnittstelle * Ersetzen Sie die ursprüngliche URL
    * Formular löschen
    */
   Bild hochladen (Artikel.Formular).then (res => {
    Artikel.URL = Res.Daten.URL
    item.form löschen
    Entschlossenheit (res)
   }).catch(err => {
    ablehnen (Fehler)
   })
  })
 )
})
Versprechen.alles(Anfrage).dann(res => {
 // ... einreichen ...
})

Warten Sie bis zum letzten Schritt mit der Übermittlung der Daten, laden Sie dann alle Bilder hoch und rufen Sie nach Abschluss des Uploads die Schnittstelle zur Übermittlung der Daten auf! !

In dem Szenario, in dem es ein Formular mit mehreren Dateneingaben gibt, ist dies der richtige Ansatz!

Abschließende Zusammenfassung

Eigentlich ist es nicht kompliziert. Der Schlüssel liegt in der Planung der Datenstruktur, der Komponenteninteraktionsverarbeitung, der logischen Methoden usw. Solange die Kernpunkte dieses Schritts erreicht werden.

Bei anderen Erweiterungsvorgängen, z. B. dem Hinzufügen neuer Komponenten, dem Hinzufügen neuer Vorgänge usw., stellen die verbleibenden Probleme kein Problem mehr dar!

Dies kann lediglich als vereinfachte Version angesehen werden. Sie können es nach Ihren Bedürfnissen optimieren, überdenken, verbessern und in Ihr eigenes Wissen aufnehmen!

Wenigstens habe ich meinen Arbeitsbedarf erfüllt, hahahahaha~~~

Weitere Einzelheiten finden Sie im Quellcode. Hier ist die Github-Adresse. Vielen Dank für Ihren Stern. Ich bin Li Bai und trinke keinen Tee.

Oben sind die Details der Implementierung eines visuellen Drag-and-Drop-Seiteneditors durch Vue aufgeführt. Weitere Informationen zum visuellen Drag-and-Drop-Seiteneditor von Vue finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Benutzerdefinierte Vue-Anweisungen zum Erzielen eines vierseitigen Streckungs- und diagonalen Streckungseffekts beim Ziehen von Popup-Fenstern
  • VUE implementiert Studio-Management-Hintergrund, um die Fenstergröße durch Ziehen und Ablegen der Maus zu ändern
  • VUE implementiert eine Popup-Komponente, die nach Belieben gezogen werden kann
  • Beispielcode für eine schwebende, verschiebbare Vue-Schaltfläche
  • Implementierung einer Drag & Drop-Funktion basierend auf Vue
  • Drag-Effekt basierend auf Vue realisieren
  • Vue implementiert Div Drag & Drop
  • Vue implementiert Drag & Drop
  • Vue Draggable realisiert die Drag-Funktion von links nach rechts
  • Vue implementiert Drag-Window-Funktion

<<:  Lösung für die MySQL-Installationsaufforderung „Geben Sie für weitere Hilfe bitte NET HELPMSG 3534 ein“

>>:  Detaillierte Schritte zum Starten des Django-Projekts mit nginx+uwsgi

Artikel empfehlen

CentOS 7 SSHD ändern | Root-Login und SSHD-Port-Skriptdefinition verbieten

1. Erstellen Sie einen neuen Benutzer wwweee000 [...

JavaScript zum Erreichen eines einfachen Bildwechsels

In diesem Artikel wird der spezifische Code für J...

So installieren Sie eine MySQL-Datenbank im Deepin 2014-System

Deepin 2014 herunterladen und installieren Zum He...

Detaillierte Erklärung der MySQL-Datengruppierung

Gruppe erstellen Die Gruppierung wird in der GROU...

Verwenden von CSS zum Implementieren einer Ladeanimation des Android-Systems

Im Web gibt es zwei gängige Ladesymbole: eines is...

Welche Nachteile hat die Bereitstellung der Datenbank in einem Docker-Container?

Vorwort Docker erfreut sich seit zwei Jahren groß...

Erfahrungsaustausch zur Optimierung von MySQL-Big-Data-Abfragen (empfohlen)

Ernsthafte MySQL-Optimierung! Wenn die MySQL-Date...

So fragen Sie schnell 10 Millionen Datensätze in MySQL ab

Inhaltsverzeichnis Normale Paging-Abfrage So opti...

CSS3 verwendet var()- und calc()-Funktionen, um Animationseffekte zu erzielen

Wissenspunkte in der Vorschau anzeigen. Animation...