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:
Objektreferenz: Das ist der coolste Trick, den ich je gesehen habe. Lassen Sie mich die Details einzeln erklären! ! Drag & Drop-ImplementierungZiehen von EreignissenHier 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 StartenDefinieren 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-ZoneWä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, WinkelberechnungKernvariablen:
Wenn 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 }
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 ziehenSobald Sie die Maus loslassen oder den Freigabebereich verlassen, wird der Ausgangszustand wiederhergestellt. Welche Rolle spielt der Status hier?
// 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öckeAus 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) KomponentenabteilungDie 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 DatenstrukturUm 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
....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-UploadOben 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>
// 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 ZusammenfassungEigentlich 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:
|
>>: Detaillierte Schritte zum Starten des Django-Projekts mit nginx+uwsgi
1. Erstellen Sie einen neuen Benutzer wwweee000 [...
In diesem Artikel wird der spezifische Code für J...
Deepin 2014 herunterladen und installieren Zum He...
Ich bin auf die Anforderung gestoßen, Tastenkombi...
Gruppe erstellen Die Gruppierung wird in der GROU...
Experimentelle Umgebung: Physische Maschine Windo...
Verwenden Sie MySQL proxies_priv (simulierte Roll...
Im Web gibt es zwei gängige Ladesymbole: eines is...
In diesem Artikel wird die Methode vorgestellt, m...
Vorwort Docker erfreut sich seit zwei Jahren groß...
Ernsthafte MySQL-Optimierung! Wenn die MySQL-Date...
Code kopieren Der Code lautet wie folgt: <div ...
Inhaltsverzeichnis Hintergrund Wirkung Ideen Hint...
Inhaltsverzeichnis Normale Paging-Abfrage So opti...
Wissenspunkte in der Vorschau anzeigen. Animation...