So verwalten Sie zwischengespeicherte Seiten in Vue

So verwalten Sie zwischengespeicherte Seiten in Vue
<am Leben erhalten>
 <Router-Ansicht />
</am Leben erhalten>

Die in Vue integrierte Komponente <keep-alive> kann uns dabei helfen, die Geschwindigkeit des sekundären Seitenzugriffs bei der Entwicklung von SPA-Anwendungen deutlich zu verbessern, indem alle Routenseiten zwischengespeichert werden (natürlich können wir auch gezielt einige Seiten zwischenspeichern). In einigen Szenarien bringt sie jedoch auch Probleme mit sich, darunter zwei Hauptwidersprüche:

  1. So löschen Sie zwischengespeicherte Seiten zum richtigen Zeitpunkt (die Keep-Alive-Komponente bietet drei Parameter zum dynamischen Konfigurieren des Cache-Status, der Effekt ist jedoch begrenzt und wird später analysiert).
  2. So können Sie mehrere unterschiedliche Seiten (dieselbe Seite mit unterschiedlichen Parametern) im selben Pfad zwischenspeichern. Beispielsweise springt die Taobao-Produktseite immer wieder zu einer anderen Produktseite.

In diesem Artikel werden hauptsächlich diese beiden Probleme behandelt, die im folgenden Text als Frage 1 und Frage 2 bezeichnet werden.

Dieser Artikel geht davon aus, dass alle Seiten „Keep-Alive“ sind.

Problem 1: Zerstörung

Wenn die Geschäftslogik komplexer wird, wächst der Routing-Stack allmählich. Theoretisch können Benutzer unendlich routen. Wir müssen zwangsläufig die im Speicher zwischengespeicherten Seitendaten verwalten. Die Seitendaten bestehen aus zwei Teilen, der Vue-Instanz und dem entsprechenden Vnode. Siehe die Definition des Cache in src/core/components/keep-alive.js im Vue-Quellcode

 this.cache = Object.create(null) //Wird zum Zwischenspeichern von vnode cache[key] => Vnode verwendet
 this.keys = [] //Wird verwendet, um den Schlüssel des zwischengespeicherten Vnode aufzuzeichnen

Nach dem Zwischenspeichern wird der Vnode nicht wiederverwendet, sondern nur die darauf gemountete Vue-Instanz wird verwendet.

if (cache[Schlüssel]) {
 vnode.componentInstance = cache[key].componentInstance //Holen Sie sich die Vue-Instanz nur vom zwischengespeicherten Vnode und hängen Sie sie an den neuen Vnode // machen Sie den aktuellen Schlüssel zum aktuellsten
 entfernen(Schlüssel, Schlüssel)
 Tasten.drücken(Taste)
}

Warum nicht? Weil es einen Fehler gibt. Die früheste Version der Implementierung verwendet den zwischengespeicherten Vnode direkt.

Von src/core/components/keep-alive.js Init-Version

Standard exportieren {
 erstellt () {
 this.cache = Objekt.erstellen(null)
 },
 rendern () {
 const childNode = this.$slots.default[0]
 const cid = childNode.componentOptions.Ctor.cid
 wenn (dieser.cache[cid]) {
  const child = childNode.child = this.cache[cid].child //Den zwischengespeicherten Vnode direkt abrufen
  childNode.elm = dies.$el = child.$el
 } anders {
  this.cache[cid] = untergeordneter Knoten
 }
 childNode.data.keepAlive = true
 untergeordneten Knoten zurückgeben
 },
 vorZerstören () {
 für (const key in this.cache) {
  dies.cache[Schlüssel].child.$destroy()
 }
 }
}

Was wir verwalten müssen, sind eigentlich Cache und Schlüssel. Keep-Alive bietet drei Parameter zur dynamischen Verwaltung des Cache:

include – Nur Komponenten mit übereinstimmenden Namen werden zwischengespeichert.
Ausschließen: Alle Komponenten, die dem Namen entsprechen, werden nicht zwischengespeichert.
max – Die maximale Anzahl von Komponenteninstanzen, die zwischengespeichert werden können.

Ihre Funktionen sind sehr einfach und auch der Quellcode ist einfach und leicht zu lesen:

Wenn wir also diese Caches verwalten möchten, besteht die einfache Lösung darin, diese drei Parameter zu bedienen, „include“ und „exclude“ zu ändern, um bestimmte Caches zwischenzuspeichern oder zu löschen. Dabei ist jedoch zu beachten, dass sie mit dem Namen der Komponente übereinstimmen:

Von src/core/components/keep-alive.js

Konstantname: ?string = getComponentName(Komponentenoptionen)

Daher werden durch das Leeren des Caches alle Instanzen einer Komponente wahllos gelöscht, was offensichtlich nicht unseren Anforderungen entspricht.

Die Logik von max besteht darin, den Cache am unteren Ende des Stapels zu leeren, wenn der Maximalwert überschritten wird.

Aus src/core/components/keep-alive.js:

wenn (diese.max && Schlüssel.Länge > parseInt(diese.max)) {
 pruneCacheEntry(Cache, Schlüssel[0], Schlüssel, this._vnode)
}

Wir müssen Problem eins lösen. Die offizielle API funktioniert nicht, also müssen wir es selbst machen. Wir müssen zwei Teilprobleme lösen:

  1. Wann zerstören
  2. Wie man zerstört

1. Wie man zerstört

Sehen wir uns zunächst an, wie man es zerstört. Wenn Sie eine Instanz zerstören möchten, ist das ganz einfach. Sie können this.$destroy() direkt verwenden. Ist das in Ordnung? Nein, der ursprüngliche Vnode und der Schlüssel bleiben weiterhin im Cache und in den Schlüsseln erhalten. Beim erneuten Besuch treten Probleme auf. Der Vnode bleibt immer erhalten, aber die Instanz darauf wurde zerstört. Zu diesem Zeitpunkt wird während des Aktualisierungsprozesses von Vue erneut eine Vue-Instanz erstellt. Das heißt, solange eine Keep-Alive-Seite this.$destroy() einmal aufruft, das Cache-Array jedoch nicht gelöscht wird, wird diese Seite beim erneuten Rendern definitiv neu erstellt und natürlich wird der gesamte Lebenszyklus neu gestartet. Das letzte Phänomen besteht darin, dass die Seite scheinbar nicht zwischengespeichert ist.

this.$destroy(); //Nicht geeignet für Keep-Alive-Komponenten

Daher müssen zum Löschen sowohl der Cache als auch die Schlüssel gelöscht werden. Im Folgenden wird eine $keepAliveDestroy-Methode definiert, die gleichzeitig den Cache löscht:

 const dtmp = Vue.prototype.$destroy;
 const f = Funktion() {
 wenn (dies.$vnode und dieses.$vnode.data.keepAlive) {
  wenn (diese.$vnode.parent && dies.$vnode.parent.componentInstance && dies.$vnode.parent.componentInstance.cache) {
  wenn (this.$vnode.componentOptions) {
   var Schlüssel = !isDef(this.$vnode.key)
   ? dies.$vnode.componentOptions.Ctor.cid + (dies.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
   : dies.$vnode.key;
   var cache = this.$vnode.parent.componentInstance.cache;
   var Schlüssel = this.$vnode.parent.componentInstance.keys;
   if (cache[Schlüssel]) {
   if (Schlüssel.Länge) {
    var index = keys.indexOf(Schlüssel);
    wenn (Index > -1) {
    Schlüssel.splice(Index, 1);
    }
   }
   Cache[Schlüssel] löschen;
   }
  }
  }
 }
 dtmp.apply(diese, Argumente);
 }
 Vue.prototype.$keepAliveDestroy = f;

2. Wann vernichten

Wann wird es also zerstört? Es gibt zwei Auslösezeitpunkte:

  1. Beim Ersetzen Seite A --Ersetzen--> Seite B (Seite A löschen)
  2. Beim Zurückleiten Seite A --push--> Seite B --back--> Seite A (Seite B löschen)

Ersetzen ist relativ einfach. Wir können die Ersetzungsmethode des Routers direkt abfangen und in dieser Methode die aktuelle Seite löschen. (Hier gibt es Ausnahmen, z. B. beim Wechseln zwischen Tabs, die zuletzt erwähnt werden)

Schauen wir uns die Situation mit der Zurück-Route genauer an. Wenn es auf unserer Seite eine Zurück-Schaltfläche gibt, ist es an der Zeit, den Cache zu leeren. Allerdings können wir die integrierte Zurück-Schaltfläche des Browsers und die physische Zurück-Schaltfläche auf Android-Telefonen nicht ignorieren. Wenn man dies berücksichtigt, ist die Lösung, nur die Zurück-Schaltfläche zu verwenden, nicht ausreichend.

2.1 Lösung 1: Verwenden Sie route.query, um die aktuelle Seitenstapeltiefe aufzuzeichnen

Jedes Push oder Replace fügt der Abfrage einen Parameter hinzu, um die aktuelle Tiefe aufzuzeichnen.

dies.$router.push({
 Pfad:"/Ziel",
 Abfrage:{
 stackLevel: Zahl(this.$route.query.stackLevel) + 1 	
 }
})

Diese Lösung hat offensichtliche Nachteile. Es ist sehr hässlich und gefährlich, einen Parameter extern verfügbar zu machen. Benutzer können ihn nach Belieben ändern. Beim Bewerben einer Website kann der vom Unternehmen in die Produktionsumgebung kopierte Werbelink auch das seltsame Suffix https://xxx.com/foo?bar=123&stackLevel=13 haben. Missbilligung

2.2 Lösung 2 verwendet die Vue-Instanz selbst, um die aktuelle Stapeltiefe aufzuzeichnen

Nachdem die Push- und Replace-Methoden des Routers gehackt wurden, kann bei jedem Seitensprung ein _stackLevel auf der VM der Zielseite gemountet werden. Dies löst das Problem der ersten Lösung. Es wird den Benutzern nicht angezeigt, ist in der URL nicht sichtbar und kann nicht geändert werden. Wir können jedoch einen anderen Dämon im Browser nicht ignorieren – die Schaltfläche „Aktualisieren“. Beim Aktualisieren ändert sich die URL nicht, aber die VM-Instanz muss neu erstellt werden, sodass unsere Stapeltiefenmarkierung verloren geht. Missbilligung

2.3 Lösung 3: Verwenden Sie history.state, um die Stapeltiefe aufzuzeichnen

Das Endergebnis ist dann für den Benutzer unsichtbar und kann beim Aktualisieren gespeichert werden. Das ist history.state. Wir müssen also die Stapeltiefe in history.state speichern, wodurch die gesamte Routing-Kette vollständig gespeichert werden kann.

Wenn wir feststellen, dass die Stapeltiefe der Zielseite geringer ist als die der aktuellen Seite, können wir die aktuelle Seite zerstören.

wenn (Zielstapel < aktueller Stapel) {
 aktuell.$keepAliveDestroy();
}

Problem 2: Mehrere Instanzen derselben Seite mit unterschiedlichen Parametern zwischenspeichern

Sie können src/core/components/keep-alive.js im Quellcode sehen

const-Schlüssel: ?string = vnode.key == null
 // derselbe Konstruktor kann als unterschiedliche lokale Komponenten registriert werden
 // daher reicht cid allein nicht aus (#3269)
 ? KomponenteOptions.Ctor.cid + (KomponenteOptions.tag ? `::${KomponenteOptions.tag}` : '')
 : vnode.schlüssel
 if (cache[Schlüssel]) {
 vnode.componentInstance = cache[Schlüssel].componentInstance
 // aktuellen Schlüssel auf den neuesten Stand bringen
 entfernen(Schlüssel, Schlüssel)
 Tasten.drücken(Taste)
 } anders {
 Cache[Schlüssel] = vnode
 Tasten.drücken(Taste)
 // ältesten Eintrag löschen
 wenn (diese.max && Schlüssel.Länge > parseInt(diese.max)) {
  pruneCacheEntry(Cache, Schlüssel[0], Schlüssel, this._vnode)
 }
 }

Wenn ein vnode keinen Schlüssel hat, wird der Komponentenname verwendet. Daher ist der Schlüssel im Standardcache der Komponentenname. Wenn die Komponenten gleich sind, können wir dieses Problem lösen, indem wir jeder Seite einen eigenen Schlüssel geben. Wie können wir erreichen, dass jede Seite einen eigenen Schlüssel hat? Es gibt zwei Unterfragen:

  1. So werden Sie einzigartig
  2. So weisen Sie dem Vnode der Seite einen Schlüssel zu

1. So werden Sie einzigartig

1.1 Zeitstempel, große Zufallszahl

Schlüssel = Datum.jetzt()

1.2 Routing-Stackhöhe + Pfadname

key = vm._stack + router.currentRoute.path Diese Lösung verwendet die aktuelle Stackhöhe + Pfadnamen. Wozu wird der Pfadname benötigt? Weil beim Ersetzen die Stackhöhe unverändert bleibt, ändert sich nur der Pfadname.

2. So weisen Sie dem Vnode einer Seite einen Schlüssel zu

Derzeit gibt es zwei Lösungen, um dem Schlüssel des aktuellen Vnode des Vue-Routers einen Wert zuzuweisen:

2.1 Schlüssel dynamisch über route.query binden

Diese Lösung ist relativ einfach zu implementieren

// Taste binden
...
<router-view :key='$route.query.routerKey' />
...


//Beim Pushen von this.$router.push({
 Pfad: „/foo“,
 Abfrage:{
 	routerKey: Date.now() //Zufälliger Schlüssel
 }
})

Diese Methode ist sehr einfach und effektiv, hat aber den Nachteil, dass sie auch einen seltsamen Parameter in der URL offenlegt

2.2 Direkte Wertezuweisung durch Abrufen von Vnode

In welcher Phase wird der Schlüssel von Vnode zugewiesen? Die Antwort ist offensichtlich. Bevor die Keep-Alive-Komponenten-Renderfunktion eintritt, src/core/components/keep-alive.js

...
 rendern () {
 const slot = this.$slots.default
 const vnode: VNode = getFirstComponentChild(Steckplatz)
...

Wir können die Keep-Alive-Renderfunktion hacken, dann den ersten untergeordneten Knoten im Slot abrufen, seinem Schlüssel einen Wert zuweisen und dann das Keep-Alive-Rendern aufrufen:

const tmp = vm.$options.render //vm ist eine Keep-Alive-Komponenteninstanz
vm.$options.render = Funktion() {
 const slot = this.$slots.default;
 const vnode = getFirstComponentChild(slot) // vnode ist ein Keep-Alive-Komponenten-vnode
 if (VerlaufSollteÄndern) {
 wenn (!isDef(vnode.key)) {
  if (istErsetzen) {
  vnode.key = genKey(router._stack)
  } sonst wenn (isPush()) {
  vnode.key = genKey(Zahl(router._stack) + 1)
  } anders {
  vnode.key = genKey(Zahl(router._stack) - 1)
  }
 }
 } anders {
 // wenn historyShouldChange false ist, sollte nur erneut gerendert werden, es sollte keine neue VM erstellt werden, verwenden Sie den gleichen vnode.key, Problem Nr. 7
 vnode.key = genKey(router._stack)
 }
 returniere tmp.apply(diese, Argumente)
}

Zusammenfassen

Durch die obige Problemanalyse haben wir das Kernproblem der automatischen Cache-Verwaltung gelöst. Dieser Artikel ist eine Zusammenfassung der Open-Source-Bibliothek vue-router-keep-alive-helper. Diese Bibliothek ist ein einfaches und benutzerfreundliches Tool zur automatischen Verwaltung des Keep-Alive-Cache, das das Problem der Vue-Cache-Verwaltung löst. Wenn es für Sie nützlich ist, danke für Ihren großzügigen Stern.

Demo-Beispielcode

Danke für das Bilibili-Demovideo.

Oben finden Sie Einzelheiten zum Verwalten zwischengespeicherter Seiten in Vue. Weitere Informationen zu zwischengespeicherten Seiten in Vue finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Beheben Sie das Problem, dass die Seite nicht mehr zwischengespeichert wird, wenn Vue Keep-Alive $destory() aufruft.
  • Vue verwendet den lokalen Cache von localStorage, um die Funktion zum Aktualisieren des Bestätigungscodes ohne Löschen zu implementieren
  • Vue-Seitensprung, um einen Seitencache-Vorgang zu erreichen
  • Lösen Sie das Keeplive-Cache-Problem der Vue-Einzelseiten-Fallbackseite
  • Beispielcode zum Keeping-Alive mit Vue-Router, um einen Cache-Seiteneffekt zu erzielen
  • So implementieren Sie Seiten-Caching und Nicht-Caching in Vue2.0
  • Beispiel für das erzwungene Löschen des Seitencaches in einem Vue-Projekt
  • Mehrere Möglichkeiten zum Wechseln zwischen Vue Tab und Cache-Seiten
  • Detaillierte Erklärung zum Seiten-Caching in Vue
  • So aktualisieren Sie die Daten einer Keepalive-Seite im Vue-Cache

<<:  Tutorial zum Konfigurieren und Verwenden des i3-Fenstermanagers unter Linux

>>:  MySQL erstellt Benutzer, autorisiert Benutzer, widerruft Benutzerberechtigungen, ändert Benutzerkennwörter und löscht Benutzer (praktische Tipps)

Artikel empfehlen

Installation von CUDA10.0 und Probleme in Ubuntu

Die Entsprechung zwischen der Tensorflow-Version ...

Drei häufig verwendete MySQL-Datentypen

Das Definieren des Datenfeldtyps in MySQL ist für...

Beispielcode für den dynamischen CSS-Ladebalkeneffekt

Mit dem Wissen über CSS-Variablen werde ich den C...

Implementierung von zwei Basis-Images für die Docker-Bereitstellung von Go

1. golang:neuestes Basis-Image mkdir gotest Berüh...

Verwendung und Beschreibung des HTML-Tags tbody

Das Tbody-Element sollte in Verbindung mit den Ele...

Tutorial zur Installation und Kennwortkonfiguration von MySQL 5.7.21

Tutorial zur Installation und Kennworteinstellung...

Detailliertes Beispiel für die Datenmigration bei einem IOS-Datenbank-Upgrade

Detailliertes Beispiel für die Datenmigration bei...

Zusammenfassung zur Verwendung der Bootstrap-Tabelle

In diesem Artikel erfahren Sie, wie Sie die Boots...