Zusammenfassung der bei der Implementierung von Vue-Plugins aufgetretenen Probleme

Zusammenfassung der bei der Implementierung von Vue-Plugins aufgetretenen Probleme

Szeneneinführung

Beim Arbeiten an H5 bin ich kürzlich auf ein Szenario gestoßen: Jede Seite muss eine Kopfzeile mit einem Titel anzeigen. Eine Implementierungsidee ist die Verwendung globaler Komponenten. Angenommen, wir erstellen eine globale Komponente namens TheHeader.vue. Der Pseudocode lautet wie folgt:

<Vorlage>
    <h2>{{ Titel }}</h2>
</Vorlage>

<Skript>
Standard exportieren {
Requisiten: {
    Titel:
        Typ: Zeichenfolge,
        Standard: ''
    }
}
}
</Skript>

Nachdem Sie die globale Komponente erstellt haben, verweisen Sie in jeder Seitenkomponente darauf und übergeben Sie sie an Props. Wenn wir beispielsweise auf diese Komponente auf Seite A verweisen, ist die Komponente, die Seite A entspricht, A.vue

<Vorlage>
    <div>
        <TheHeader :title="Titel" />
    </div>
</Vorlage>
<Skript>
    Standard exportieren {
        Daten() {
            Titel: ''
        },
        erstellt(){
            this.title = 'Meine Homepage'
        }
    }
</Skript>

Die Verwendung ist sehr einfach, es gibt jedoch einen Nachteil: Wenn die Header-Komponente viele Requisiten übergeben muss, ist es mühsam, die entsprechenden Requisiten in der Seitenkomponente beizubehalten. In diesem Fall gibt es eine bessere Idee zur Implementierung dieses Szenarios, nämlich die Verwendung des Vue-Plug-Ins.

Die gleiche Methode zum Aufrufen der Kopfkomponente in der A.vue-Komponente ist bei Verwendung des Vue-Plugins prägnanter:

<Vorlage>
    <div />
</Vorlage>
<Skript>
    Standard exportieren {
        erstellt(){
            this.$setHeader('Meine Homepage')
        }
    }
</Skript>

Wir können sehen, dass bei Verwendung des Vue-Plugins zur Implementierung die TheHeader-Komponente nicht explizit in A.vue eingefügt werden muss und auch die entsprechenden Props nicht in die Datenfunktion von A.vue eingefügt werden müssen. Sie müssen nur eine Funktion aufrufen. Also, wie funktioniert dieses Plugin?

Plugin-Implementierung

Die konkreten Schritte zur Umsetzung sind wie folgt:

  1. Erstellen Sie eine SFC (Single File Component), hier ist die Header-Komponente
  2. Erstellen Sie eine plugin.js-Datei, führen Sie SFC ein und verwenden Sie die Vue.extend-Methode, um einen neuen Vue-Konstruktor zu erhalten und ihn zu instanziieren.
  3. Instanziieren und aktualisieren Sie eine Vue-Komponenteninstanz über einen Funktionsaufruf.

Lassen Sie uns anhand der obigen Schritte eine Datei plugin.js erstellen:

importiere TheHeader aus './TheHeader.vue'
Vue von „vue“ importieren

const headerPlugin = {
    installieren(Vue) {
        const vueInstance = neu (Vue.extend(TheHeader))().$mount()
        Vue.prototype.$setHeader = Funktion(Titel) {
            vueInstance.title = Titel
            Dokument.body.prepend(vueInstance.$el)
            
        }
    }
}
Vue.use(headerPlugin)

Anschließend führen wir plugin.js in main.js ein, um den gesamten logischen Prozess der Plugin-Implementierung abzuschließen. Obwohl dieses Plugin implementiert wurde, gibt es jedoch einige Probleme.

Problem 1: Doppelte Header-Komponenten

Wenn wir es in einer Einzelseitenkomponente verwenden, werden wir, solange wir die Methode router.push verwenden, auf ein magisches Problem stoßen: Auf der neuen Seite werden zwei Header-Komponenten angezeigt. Wenn wir noch ein paar Mal springen, erhöht sich auch die Anzahl der Kopfkomponenten. Dies liegt daran, dass wir diese Methode auf jeder Seite aufrufen, sodass jede Seite das entsprechende DOM in das Dokument einfügt.

Unter Berücksichtigung dessen müssen wir die oben genannten Komponenten optimieren. Wir platzieren den Instanziierungsprozess außerhalb des Plugins:

importiere TheHeader aus './TheHeader.vue'
Vue von „vue“ importieren

const vueInstance = neu (Vue.extend(TheHeader))().$mount()
const headerPlugin = {
    installieren(Vue) {
        Vue.prototype.$setHeader = Funktion(Titel) {
            vueInstance.title = Titel
            Dokument.body.prepend(vueInstance.$el)
            
        }
    }
}
Vue.use(headerPlugin)

Bei diesem Vorgang wird das DOM immer noch wiederholt in das Dokument eingefügt. Da es sich jedoch um dieselbe Vue-Instanz handelt, hat sich der entsprechende DOM nicht geändert, sodass immer nur ein eingefügtes DOM vorhanden ist. Auf diese Weise haben wir das Problem der Anzeige mehrerer Header-Komponenten gelöst. Um den Vorgang des Einfügens in das DOM nicht wiederholen zu müssen, können wir auch eine Optimierung vornehmen:

importiere TheHeader aus './TheHeader.vue'
Vue von „vue“ importieren

const vueInstance = neu (Vue.extend(TheHeader))().$mount()
const hasPrepend = false
const headerPlugin = {
    installieren(Vue) {
        Vue.prototype.$setHeader = Funktion(Titel) {
            vueInstance.title = Titel
            wenn (!hasPrepend) {
                Dokument.body.prepend(vueInstance.$el)
                hasPrepend = true
            }
            
        }
    }
}
Vue.use(headerPlugin)

Fügen Sie eine Variable hinzu, um zu steuern, ob das DOM eingefügt wurde. Wenn es eingefügt wurde, wird der Einfügevorgang nicht ausgeführt. Nach der Optimierung ist die Implementierung dieses Plugins fast abgeschlossen. Allerdings bin ich während der Implementierung auf mehrere Probleme gestoßen, die ich hier aufzeichnen werde.

Frage 2: Eine andere Implementierungsidee

Während des Implementierungsprozesses kam mir plötzlich eine Idee: Kann ich die Datenfunktion der TheHeader-Komponente direkt ändern, um diese Komponente zu implementieren? Sehen Sie sich den folgenden Code an:

importiere TheHeader aus './TheHeader.vue'
Vue von „vue“ importieren

let el = null
const headerPlugin = {
    installieren(Vue) {
        Vue.prototype.$setHeader = Funktion(Titel) {
            TheHeader.data = function() {
                Titel
            }
            const vueInstance = neu (Vue.extend(TheHeader))().$mount()
            el = vueInstance.$el
            wenn (el) {
                Dokument.Body.RemoveChild(el)
                Dokument.Body.prepend(el)
            }
            
        }
    }
}
Vue.use(headerPlugin)

Es sieht nicht so aus, als ob damit irgendetwas nicht stimmt. Nach einiger Übung stellte sich jedoch heraus, dass beim Aufruf der Methode $setHeader nur der erste übergebene Wert wirksam wird. Wenn beispielsweise die erste Eingabe „Meine Homepage“ und die zweite Eingabe „Persönliche Daten“ lautet, wird in der Header-Komponente immer „Meine Homepage“ und nicht „Persönliche Daten“ angezeigt. Was ist der Grund?

Nach eingehender Untersuchung des Vue-Quellcodes stellte sich heraus, dass Header nach dem ersten Aufruf von new Vue eine zusätzliche Ctor-Eigenschaft hatte, die den der Header-Komponente entsprechenden Konstruktor zwischenspeicherte. Beim nachfolgenden Aufruf von new Vue(TheHeader) wird immer der erste Cache als Konstruktor verwendet, der Wert des Titels ändert sich also nicht. Der dem Vue-Quellcode entsprechende Code lautet wie folgt:

Vue.extend = Funktion (Erweiterungsoptionen) {
    erweiternOptionen = erweiternOptionen || {};
    var Super = dies;
    var SuperId = Super.cid;
    var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {}); 
    if (cachedCtors[SuperId]) { // Wenn ein Cache vorhanden ist, gib den zwischengespeicherten Konstruktor direkt zurück return cachedCtors[SuperId]
    }

    var name = extendOptions.name || Super.options.name;
    wenn (Prozess.env.NODE_ENV !== 'Produktion' && Name) {
      validiereKomponentenname(Name);
    }

    var Sub = Funktion VueComponent (Optionen) {
      this._init(Optionen);
    };
    Sub.prototype = Objekt.erstellen(Super.prototype);
    Sub.prototype.constructor = Sub;
    Sub.cid = cid++;
    Untergeordnete Optionen = MergeOptions(
      Super.options,
      Erweiterungsoptionen
    );
    Sub['super'] = Super;

    // Für Props und berechnete Eigenschaften definieren wir die Proxy-Getter auf
    // die Vue-Instanzen zur Erweiterungszeit, auf dem erweiterten Prototyp. Dies
    // vermeidet Object.defineProperty-Aufrufe für jede erstellte Instanz.
    wenn (Sub.options.props) {
      : InitProps$1(Sub);
    }
    wenn (Sub.options.computed) {
      initComputed$1(Sub);
    }

    // weitere Nutzung von Erweiterungen/Mixins/Plugins zulassen
    Sub.extend = Super.extend;
    Sub.mixin = Super.mixin;
    Sub.use = Super.use;

    // Asset-Register erstellen, also erweiterte Klassen
    // können auch über ihr Privatvermögen verfügen.
    ASSET_TYPES.forEach(Funktion (Typ) {
      Sub[Typ] = Super[Typ];
    });
    // rekursive Selbstsuche aktivieren
    wenn (Name) {
      Sub.Optionen.Komponenten[Name] = Sub;
    }

    // Behalten Sie zum Zeitpunkt der Erweiterung einen Verweis auf die Superoptionen bei.
    // später bei der Instanziierung können wir prüfen, ob die Optionen von Super
    // wurde aktualisiert.
    Sub.superOptions = Super.options;
    Sub.extendOptions = Erweiterungsoptionen;
    Sub.sealedOptions = erweitern({}, Sub.options);

    // Cache-Konstruktor
    cachedCtors[SuperId] = Sub; // Hier wird der Ctor-Konstruktor zwischengespeichert return Sub
  }

Nachdem wir den Grund gefunden haben, werden wir feststellen, dass diese Methode auch möglich ist. Wir müssen nur eine Codezeile in plugin.js hinzufügen

importiere TheHeader aus './TheHeader.vue'
Vue von „vue“ importieren

let el = null
const headerPlugin = {
    installieren(Vue) {
        Vue.prototype.$setHeader = Funktion(Titel) {
            TheHeader.data = function() {
                Titel
            }
            DerHeader.Ctor = {}
            const vueInstance = new Vue(DerHeader).$mount()
            el = vueInstance.$el
            wenn (el) {
                Dokument.Body.RemoveChild(el)
                Dokument.Body.prepend(el)
            }
            
        }
    }
}
Vue.use(headerPlugin)

Jedes Mal, wenn wir die Methode $setHeader ausführen, entfernen wir einfach den zwischengespeicherten Konstruktor.

Frage 3: Ist es möglich, Vue.extend nicht zu verwenden?

Tatsächlich ist es möglich, Vue direkt zu verwenden, ohne Vue.extend zu verwenden. Der entsprechende Code lautet wie folgt:

importiere TheHeader aus './TheHeader.vue'
Vue von „vue“ importieren

const vueInstance = new Vue(DerHeader).$mount()
const hasPrepend = false
const headerPlugin = {
    installieren(Vue) {
        Vue.prototype.$setHeader = Funktion(Titel) {
            vueInstance.title = Titel
            wenn (!hasPrepend) {
                Dokument.body.prepend(vueInstance.$el)
                hasPrepend = true
            }
            
        }
    }
}
Vue.use(headerPlugin)

Die direkte Verwendung von Vue zum Erstellen einer Instanz ist besser als die Verwendung von Extend zum Erstellen einer Instanz, da dabei die Ctor-Eigenschaft in Header.vue nicht zwischengespeichert wird. Aber ich habe schon einmal gesehen, wie Vant die Toast-Komponente implementiert hat, die im Grunde die Vue.extend-Methode verwendet, anstatt Vue direkt zu verwenden. Warum ist das so?

Zusammenfassen

Dies ist das Ende dieses Artikels über die Probleme, die bei der Implementierung von Vue-Plug-Ins aufgetreten sind. Weitere relevante Probleme bei der Implementierung von Vue-Plug-Ins 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 zum Schreiben und Verwenden von Vue-Plugins (mit Demo)
  • Das Vue-Rechtsklickmenü-Plugin ist ein einfaches, erweiterbares und anpassbares Rechtsklickmenü
  • Verwendung benutzerdefinierter globaler Vue-Komponenten (benutzerdefinierte Plug-Ins)
  • Vue3.0 implementiert Plugin-Kapselung
  • Detaillierte Erklärung der Vue.js-Plugin-Entwicklung
  • Installieren Sie das Plugin im Vue-Projekt und speichern Sie

<<:  IIS-Konfiguration des Win Server 2019-Servers und einfache Veröffentlichung der Website

>>:  Lösung für das Problem des Datenverlusts bei Verwendung der Ersetzungsoperation in MySQL

Artikel empfehlen

W3C Tutorial (13): W3C WSDL Aktivitäten

Bei Webdiensten geht es um die Kommunikation zwis...

Lösung für das Problem des Sitzungsverlusts bei Nginx

Bei der Verwendung von Nginx als Reverse-Proxy fü...

Detaillierte Erklärung der allgemeinen Verwendung von MySQL-Abfragebedingungen

Dieser Artikel veranschaulicht anhand von Beispie...

Eine kurze Diskussion über den VUE Uni-App-Lebenszyklus

Inhaltsverzeichnis 1. Anwendungslebenszyklus 2. S...

So beheben Sie den Fehler "ERROR 1045 (28000)" beim Anmelden bei MySQL

Heute habe ich mich beim Server angemeldet und mi...

Eine kurze Analyse der expliziten Typkonvertierung von MySQL

CAST-Funktion Im vorherigen Artikel haben wir die...

Häufig verwendete JavaScript-Array-Methoden

Inhaltsverzeichnis 1. filter() 2. fürJedes() 3. e...

Detaillierte Erläuterung des Grafikbeispiels für Vue-Überwachungsattribute

Inhaltsverzeichnis Was ist die Listener-Eigenscha...

NULL und leere Zeichenfolge in MySQL

Ich bin vor kurzem mit MySQL in Berührung gekomme...

So konvertieren Sie Zeilen in Spalten in MySQL

MySQL-Zeilen-zu-Spalten-Operation Die sogenannte ...

So konfigurieren Sie den Nginx-Lastausgleich

Inhaltsverzeichnis Nginx-Lastausgleichskonfigurat...

Reines CSS3 zum Erstellen eines Beispielcodes für Haushühner

Ich habe in letzter Zeit viel Wissen und Artikel ...

Eine kurze Zusammenfassung von Vue Keep-Alive

1. Funktion Wird hauptsächlich verwendet, um den ...