Um die Wirkung direkt zu sehen, wurde ein Rechtsklickmenü hinzugefügt, welches die Funktionen „Neu laden“, „Links schließen“, „Rechts schließen“ und „Weitere schließen“ umfasst. Sie können sich den Code auch auf meinem GitHub ansehen (wenn Sie diese Komponente nützlich finden, vergessen Sie nicht, ihr einen Stern zu geben). Code: https://github.com/Caijt/VuePageTab Demo: https://caijt.github.io/VuePageTab/ Die Methode zum Löschen des Caches in meiner Multi-Tab-Komponente besteht nicht darin, die Einschluss- und Ausschlusskombination der Keep-Alive-Komponente zu verwenden, sondern die Brute-Force-Methode zum Löschen des Caches. Dies wurde auch im vorherigen Blog erwähnt. Mit dieser Methode kann eine umfassendere Multi-Tab-Funktion erreicht werden. Beispielsweise kann dieselbe Route gemäß unterschiedlichen Parametern gleichzeitig verschiedene Tabs öffnen, und es besteht keine Notwendigkeit, die Namenswerte dieser Routen zu schreiben. Schauen wir uns zunächst den Komponentencode direkt an (darin werden einige Element-UI-Komponenten verwendet. Wenn Sie Element-UI nicht verwenden, können Sie diese entfernen und selbst implementieren). <Vorlage> <div Klasse="__common-layout-pageTabs"> <el-Bildlaufleiste> <div Klasse="__tabs"> <div Klasse="__tab-item" v-for="Element in geöffneten Seitenroutern" :Klasse="{ '__ist aktiv': item.fullPath == $route.fullPath, }" :Schlüssel="item.vollständigerPfad" @click="beimKlick(Element)" @contextmenu.prevent="showContextMenu($event, item)" > {{ item.meta.title }} <span Klasse="el-icon-close" @click.stop="beimSchließen(Element)" @contextmenu.prevent.stop="" :style="openedPageRouters.length <= 1 ? 'width:0;' : ''" ></span> </div> </div> </el-scrollbar> <div v-show="contextMenuSichtbar"> <ul :style="{ links: contextMenuLeft + 'px', oben: contextMenuTop + 'px' }" Klasse="__Kontextmenü" > <li> <el-button Typ="Text" @click="reload()" Größe="mini"> Neu laden</el-button> </li> <li> <el-Schaltfläche Typ="Text" @click="schließenAndereLinks" :deaktiviert="false" Größe="mini" >Schließen links</el-Button > </li> <li> <el-Schaltfläche Typ="Text" @click="AnderesRechtsschließen" :deaktiviert="false" Größe="mini" >Rechts schließen</el-Button > </li> <li> <el-button Typ="Text" @click="schließenAndere" Größe="mini" >Andere schließen</el-button > </li> </ul> </div> </div> </Vorlage> <Skript> Standard exportieren { Requisiten: { keepAliveComponentInstance: {}, //Keep-Alive-Steuerinstanzobjekt blankRouteName: { Typ: Zeichenfolge, Standard: "leer", }, //leerer Routenname-Wert}, Daten() { zurückkehren { contextMenuVisible: false, //Gibt an, ob das Rechtsklickmenü angezeigt wirdcontextMenuLeft: 0, //Anzeigeposition des RechtsklickmenüscontextMenuTop: 0, //Anzeigeposition des RechtsklickmenüscontextMenuTargetPageRoute: null, //Menüroute, auf die die rechte Maustaste zeigtopenedPageRouters: [], //Geöffnete Routenseiten}; }, betrachten: //Wenn sich die Route ändert, führe die Methode zum Öffnen der Seite aus $route: { handler(v) { diese.öffnenSeite(v); }, sofort: wahr, }, }, montiert() { //Klick hinzufügen, um das Rechtsklickmenü zu schließen window.addEventListener("click", this.closeContextMenu); }, zerstört() { window.removeEventListener("klicken", this.closeContextMenu); }, Methoden: { //Öffne die Seite openPage(route) { wenn (route.name == dieser.blankRoutenname) { zurückkehren; } let isExist = this.openedPageRouters.some( (Element) => Element.vollständigerPfad == Route.vollständigerPfad ); wenn (!istExistiert) { let openedPageRoute = this.openedPageRouters.find( (Element) => Element.Pfad == Routenpfad ); // Überprüfen Sie, ob die Seite mehrere Seiten mit unterschiedlichen Parametern unterstützt. Wenn dies nicht der Fall ist und bereits eine Seitenroute mit demselben Pfadwert vorhanden ist, ersetzen Sie diese, wenn (!route.meta.canMultipleOpen && openedPageRoute != null) { this.delRouteCache(openedPageRoute.fullPath); dies.openedPageRouters.splice( this.openedPageRouters.indexOf(openedPageRoute), 1, Route ); } anders { dies.openedPageRouters.push(route); } } }, //Klicken Sie auf die Registerkarte Seite onClick(route) { wenn (route.fullPath !== this.$route.fullPath) { dies.$router.push(route.fullPath); } }, //Seitentab schließen onClose(route) { let index = this.openedPageRouters.indexOf(route); diese.delPageRoute(route); wenn (route.fullPath === diese.$route.fullPath) { //Nach dem Löschen der Seite zur vorherigen Seite springen this.$router.replace( this.openedPageRouters[index == 0 ? 0 : index - 1] ); } }, //Rechtsklick, um das Menü anzuzeigenshowContextMenu(e, route) { this.contextMenuTargetPageRoute = Route; this.contextMenuLeft = e.layerX; dies.contextMenuTop = e.layerY; Dies.contextMenuVisible = true; }, //Rechtsklickmenü ausblenden closeContextMenu() { this.contextMenuVisible = falsch; this.contextMenuTargetPageRoute = null; }, //Seite neu laden reload() { dies.delRouteCache(dieses.contextMenuTargetPageRoute.fullPath); wenn (diese.contextMenuTargetPageRoute.fullPath === diese.$route.fullPath) { dies.$router.replace({ name: this.blankRouteName }).then(() => { dies.$router.replace(diese.contextMenuTargetPageRoute); }); } }, //Andere Seiten schließen closeOther() { für (lass i = 0; i < this.openedPageRouters.length; i++) { lass r = this.openedPageRouters[i]; wenn (r !== diese.contextMenuTargetPageRoute) { diese.delPageRoute(r); ich--; } } wenn (diese.contextMenuTargetPageRoute.fullPath != diese.$route.fullPath) { dies.$router.replace(diese.contextMenuTargetPageRoute); } }, //Den Index basierend auf dem Pfad abrufen getPageRouteIndex(fullPath) { für (lass i = 0; i < this.openedPageRouters.length; i++) { wenn (this.openedPageRouters[i].fullPath === fullPath) { gebe ich zurück; } } }, //Linke Seite schließen closeOtherLeft() { let index = this.openedPageRouters.indexOf( this.contextMenuZielseiteRoute ); Lassen Sie currentIndex = this.getPageRouteIndex(this.$route.fullPath); wenn (Index > aktuellerIndex) { dies.$router.replace(diese.contextMenuTargetPageRoute); } für (sei i = 0; i < Index; i++) { lass r = this.openedPageRouters[i]; diese.delPageRoute(r); ich--; Index--; } }, //Die rechte Seite schließen closeOtherRight() { let index = this.openedPageRouters.indexOf( this.contextMenuZielseiteRoute ); Lassen Sie currentIndex = this.getPageRouteIndex(this.$route.fullPath); für (lass i = Index + 1; i < this.openedPageRouters.length; i++) { lass r = this.openedPageRouters[i]; diese.delPageRoute(r); ich--; } wenn (Index < aktuellerIndex) { dies.$router.replace(diese.contextMenuTargetPageRoute); } }, //Seite löschen delPageRoute(route) { let routeIndex = this.openedPageRouters.indexOf(route); wenn (routeIndex >= 0) { dies.openedPageRouters.splice(routeIndex, 1); } dies.delRouteCache(route.fullPath); }, //Seitencache löschen delRouteCache(key) { lass cache = this.keepAliveComponentInstance.cache; Lassen Sie die Schlüssel = this.keepAliveComponentInstance.keys; für (lass i = 0; i < Schlüssel.Länge; i++) { wenn (Schlüssel[i] == Schlüssel) { Schlüssel.spleißen(i, 1); if (cache[Schlüssel] != null) { Cache[Schlüssel] löschen; } brechen; } } }, }, }; </Skript> <style lang="scss"> .__common-layout-pageTabs { .__Kontextmenü { // Breite: 100px; Rand: 0; Rand: 1px durchgezogen #e4e7ed; Hintergrund: #fff; Z-Index: 3000; Position: absolut; Listenstiltyp: keiner; Polsterung: 5px 0; Rahmenradius: 4px; Schriftgröße: 14px; Farbe: #333; Kastenschatten: 1px 1px 3px 0 rgba (0, 0, 0, 0,1); li { Rand: 0; Polsterung: 0px 15px; &:schweben { Hintergrund: #f2f2f2; Cursor: Zeiger; } Taste { Farbe: #2c3e50; } } } $c-tab-border-color: #dcdfe6; Position: relativ; &::vor { Inhalt: ""; Rahmen unten: 1px durchgehend $c-tab-border-color; Position: absolut; links: 0; rechts: 0; unten: 0; Höhe: 100%; } .__tabs { Anzeige: Flex; .__tab-item { Leerzeichen: Nowrap; Polsterung: 8px 6px 8px 18px; Schriftgröße: 12px; Rand: 1px durchgezogen $c-tab-border-color; Rand links: keiner; Rahmen unten: 0px; Zeilenhöhe: 14px; Cursor: Zeiger; Übergang: Farbe 0,3 s kubisch-bezier(0,645, 0,045, 0,355, 1), Polsterung 0,3 s kubisch-bézier (0,645, 0,045, 0,355, 1); &:erstes-Kind { Rahmen links: 1px durchgezogen $c-tab-border-color; Rahmen oben links – Radius: 2px; Rand links: 10px; } &:letztes-Kind { Rahmen oben rechts – Radius: 2px; Rand rechts: 10px; } &:nicht(.__ist-aktiv):hover { Farbe: #409eff; .el-icon-schließen { Breite: 12px; Rand rechts: 0px; } } &.__ist-aktiv { Polsterung rechts: 12px; Rahmen unten: 1px durchgezogen #fff; Farbe: #409eff; .el-icon-schließen { Breite: 12px; Rand rechts: 0px; Rand links: 2px; } } .el-icon-schließen { Breite: 0px; Höhe: 12px; Überlauf: versteckt; Randradius: 50 %; Schriftgröße: 12px; Rand rechts: 12px; Transform-Ursprung: 100 % 50 %; Übergang: alle 0,3 s kubisch-bézier (0,645, 0,045, 0,355, 1); vertikale Ausrichtung: Text oben; &:schweben { Hintergrundfarbe: #c0c4cc; Farbe: #fff; } } } } } </Stil> Diese Komponente erfordert zwei Eigenschaften, eine ist keepAliveComponentInstance (Keep-Alive-Steuerungsinstanzobjekt), blankRouteName (leerer Routenname)Warum brauche ich das Keep-Alive-Control-Instanzobjekt? Weil dieses Objekt zwei Eigenschaften hat, eine ist Cache und die andere sind Schlüssel, die die Keep-Alive-Cache-Daten speichern. Mit diesem Objekt kann ich den Cache manuell löschen, wenn die Registerkarte geschlossen wird. Wie erhält man dieses Objekt? Wie unten gezeigt, erhält man es beim gemounteten Ereignis auf der übergeordneten Seite, auf der sich Keep-Alive befindet (wenn sich Keep-Alive und die mehrseitige Registerkartenkomponente nicht auf derselben übergeordneten Seite befinden, müssen Sie möglicherweise Vuex verwenden, um den Wert zu übergeben). <Vorlage> <div id="app"> <page-tabs :keep-alive-component-instance="keepAliveComponentInstance" /> <div ref="keepAliveContainer"> <am Leben erhalten> <router-view :key="$route.fullPath" /> </am Leben erhalten> </div> </div> </Vorlage> <Skript> importiere PageTabs aus "./components/pageTabs.vue"; Standard exportieren { Name: "App", Komponenten: Seitentabs, }, montiert() { wenn (this.$refs.keepAliveContainer) { this.keepAliveComponentInstance = this.$refs.keepAliveContainer.childNodes[0].__vue__; //Holen Sie sich das Keep-Alive-Steuerungsinstanzobjekt} }, Daten() { zurückkehren { keepAliveComponentInstance: null, }; } }; </Skript> Wofür ist der Name der leeren Route? Hauptsächlich möchte ich die Funktion zum Aktualisieren der aktuellen Seite realisieren. Wir wissen, dass Vue das Springen zur aktuellen Seite nicht zulässt. Daher möchte ich zuerst zu einer anderen Seite springen und dann zur Seite zurückspringen, um den Aktualisierungseffekt zu erzielen. (Natürlich verwende ich relpace, sodass keine Verlaufsdatensätze generiert werden) Hinweis: Diese leere Route ist nicht auf die Stammroute festgelegt. Sie hängt vom Speicherort der Multi-Tab-Komponente ab. Wenn Sie eine Root-Router-Ansicht und eine Layout-Komponente haben, die auch eine untergeordnete Router-Ansicht hat, und sich die Multi-Tab-Komponente in dieser Layout-Komponente befindet, muss die leere Route in den untergeordneten Elementen der Route definiert werden, die der Layout-Komponente entspricht. Diese Komponente wird je nach Metaobjekt des Routing-Objekts auch unterschiedlich konfiguriert, wie unten gezeigt let router = neuer Router({ Routen: [ //Dies ist eine leere Seite. Beim Neuladen der aktuellen Seite wird { verwendet. Name: "leer", Pfad: "/blank", }, { Pfad: "/a", Komponente: A, Meta: { Titel: "Seite A", //Seitentitel canMultipleOpen: true //Unterstützt das Öffnen mehrerer Tabs basierend auf unterschiedlichen Parametern. Wenn Sie zwei Tabs für /a bzw. /a?v=123 öffnen müssen, setzen Sie es bitte auf true, andernfalls wird nur ein Tab angezeigt und der später geöffnete Tab ersetzt den zuvor geöffneten Tab.} } } Oben sind die Details der Implementierung von Multi-Tab-Komponenten durch Vue aufgeführt. Weitere Informationen zur Implementierung von Multi-Tab-Komponenten durch Vue finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: So verwenden Sie die HTML 5 Drag & Drop-API in Vue
>>: Ausführliche Erklärung dieses Schlüsselworts in JavaScript
1. Erstellen Sie eine Planungsaufgabe Anweisung c...
In Projekten werden häufig Batch-Operationsanweis...
Der SYN-Angriff ist die häufigste und am leichtes...
Ich habe vor, die internen Dokumente des Unterneh...
Offizielle Website-Adresse: https://www.mysql.com...
Erstellen Sie eine neue Konfigurationsdatei (gehe...
Auf alle Orchestrierungsdateien und Konfiguration...
Inhaltsverzeichnis 1. Das Konzept des Filters 1. ...
Dieser Artikel beschreibt die Linux-Dateiverwaltu...
Beim Erstellen einer Webseite verwenden Sie manchm...
1. Installieren Sie libfastcommon-1.0.43. Das Ins...
Indem wir den aktuellen Bildlaufversatz zu den At...
Inhaltsverzeichnis Umfeld: 1. Docker ermöglicht d...
Wir werden phpMyAdmin installieren, damit es mit ...
Inhaltsverzeichnis 1. Bauen Sie mit dem offiziell...