Dieser Artikel bezieht sich hauptsächlich auf das Thema, das Guillaume Chau, ein Kernmitglied von Vue.js, auf der 19. Vue-Konferenz in den USA vorstellte: „9 enthüllte Leistungsgeheimnisse“, in dem neun Techniken zur Leistungsoptimierung von Vue.js erwähnt wurden. Nachdem ich mir seine PPT-Präsentation angesehen hatte, las ich auch den entsprechenden Quellcode des Projekts. Nachdem ich ein tiefes Verständnis für die Optimierungsprinzipien gewonnen hatte, wandte ich einige der Optimierungstechniken in meiner täglichen Arbeit an und erzielte recht gute Ergebnisse. Dieses Teilen ist sehr praktisch, aber nicht viele Leute scheinen es zu kennen oder darauf zu achten. Bisher hat das Projekt nur ein paar hundert Sterne. Obwohl es zwei Jahre her ist, seit der Meister seine Erkenntnisse geteilt hat, sind die Optimierungstechniken nicht veraltet. Damit mehr Menschen die praktischen Fähigkeiten verstehen und erlernen können, habe ich beschlossen, seine Erkenntnisse weiter zu verarbeiten, die Optimierungsprinzipien näher zu erläutern und einige Erweiterungen und Erweiterungen vorzunehmen.
Ich schlage vor, dass Sie den Quellcode des Projekts abrufen und ihn lokal ausführen, wenn Sie diesen Artikel studieren, um den Unterschied in den Effekten vor und nach der Optimierung zu sehen. Funktionale KomponentenDie erste Technik, funktionale Komponenten, können Sie sich in diesem Live-Beispiel ansehen Der Komponentencode vor der Optimierung lautet wie folgt: <Vorlage> <div Klasse="Zelle"> <div v-if="Wert" Klasse="ein"></div> <Abschnitt v-else class="aus"></Abschnitt> </div> </Vorlage> <Skript> Standard exportieren { Requisiten: ['Wert'], } </Skript> Der optimierte Komponentencode lautet wie folgt: <funktionale Vorlage> <div Klasse="Zelle"> <div v-if="props.value" Klasse="ein"></div> <Abschnitt v-else class="aus"></Abschnitt> </div> </Vorlage> Anschließend haben wir 800 Komponenten vor und nach der Optimierung der übergeordneten Komponente gerendert und die Aktualisierung der Komponenten durch Ändern der Daten in jedem Frame ausgelöst. Wir haben das Chrome Performance-Bedienfeld geöffnet, um ihre Leistung aufzuzeichnen, und die folgenden Ergebnisse erhalten. Vor der Optimierung: Nach der Optimierung: Beim Vergleich dieser beiden Bilder können wir sehen, dass Warum verkürzt sich also die Ausführungszeit von JS bei Verwendung funktionaler Komponenten? Dies beginnt mit dem Implementierungsprinzip funktionaler Komponenten. Sie können es sich als eine Funktion vorstellen, die basierend auf den von Ihnen übergebenen Kontextdaten ein DOM rendern und generieren kann. Funktionale Komponenten unterscheiden sich von gewöhnlichen Objekttypkomponenten. Sie werden nicht als echte Komponenten angesehen. Wir wissen, dass während Daher verfügen funktionale Komponenten nicht über Zustände, Reaktionsdaten, Lebenszyklus-Hook-Funktionen usw. Sie können es sich so vorstellen, als ob ein Teil des DOM aus der normalen Komponentenvorlage entfernt und über eine Funktion gerendert wird. Es handelt sich um eine Art Wiederverwendung auf DOM-Ebene. Aufteilung untergeordneter KomponentenDie zweite Technik, die Aufteilung von Unterkomponenten, können Sie sich in diesem Onlinebeispiel ansehen. Der Komponentencode vor der Optimierung lautet wie folgt: <Vorlage> <div :style="{ Deckkraft: Zahl / 300 }"> <div>{{ schwer() }}</div> </div> </Vorlage> <Skript> Standard exportieren { Requisiten: ['Zahl'], Methoden: { schwer () { Konstante n = 100000 let result = 0 für (sei i = 0; i < n; i++) { Ergebnis += Math.sqrt(Math.cos(Math.sin(42))) } Ergebnis zurückgeben } } } </Skript> Der optimierte Komponentencode lautet wie folgt: <Vorlage> <div :style="{ Deckkraft: Zahl / 300 }"> <UntergeordneteKomponente/> </div> </Vorlage> <Skript> Standard exportieren { Komponenten: Kinderkompatibilität: { Methoden: { schwer () { Konstante n = 100000 let result = 0 für (sei i = 0; i < n; i++) { Ergebnis += Math.sqrt(Math.cos(Math.sin(42))) } Ergebnis zurückgeben }, }, rendern (h) { gibt h zurück('div', this.heavy()) } } }, Requisiten: ['Zahl'] } </Skript> Dann rendern wir 300 Komponenten vor und nach der Optimierung der übergeordneten Komponente und lösen die Aktualisierung der Komponenten aus, indem wir die Daten in jedem Frame ändern. Wir öffnen das Chrome Performance-Bedienfeld, um ihre Leistung aufzuzeichnen und erhalten die folgenden Ergebnisse. Vor der Optimierung: Nach der Optimierung: Beim Vergleich dieser beiden Bilder können wir erkennen, dass die Ausführungszeit Warum gibt es also einen Unterschied? Schauen wir uns die Komponenten vor der Optimierung an. Das Beispiel simuliert eine zeitaufwändige Aufgabe durch eine Die optimale Methode besteht darin, die Ausführungslogik dieser zeitaufwändigen, Ich bin jedoch anderer Meinung zu dieser Optimierungsmethode. Für Einzelheiten klicken Sie bitte auf dieses Problem. Ich denke, dass die Verwendung berechneter Eigenschaften zur Optimierung in diesem Szenario besser ist als die Aufteilung in Unterkomponenten. Dank der Caching-Funktion der berechneten Eigenschaften selbst wird zeitaufwändige Logik nur während des ersten Renderings ausgeführt und es entsteht kein zusätzlicher Overhead durch das Rendering von Unterkomponenten bei der Verwendung berechneter Eigenschaften. In der tatsächlichen Arbeit gibt es viele Szenarien, in denen berechnete Eigenschaften zur Leistungsoptimierung verwendet werden. Schließlich verkörpert es auch die Optimierungsidee des Austauschs von Raum gegen Zeit. Lokale VariablenFür den dritten Trick, lokale Variablen, können Sie sich dieses Onlinebeispiel ansehen. Der Komponentencode vor der Optimierung lautet wie folgt: <Vorlage> <div :style="{ Deckkraft: Start / 300 }">{{ Ergebnis }}</div> </Vorlage> <Skript> Standard exportieren { Requisiten: ['Start'], berechnet: { Basis () { Rückkehr 42 }, Ergebnis () { let ergebnis = this.start für (sei i = 0; i < 1000; i++) { Ergebnis += Math.sqrt(Math.cos(Math.sin(diese.Basis))) + diese.Basis * diese.Basis + diese.Basis + diese.Basis * 2 + diese.Basis * 3 } Ergebnis zurückgeben }, }, } </Skript> Der optimierte Komponentencode lautet wie folgt: <Vorlage> <div :style="{ Deckkraft: Start / 300 }">{{ Ergebnis }}</div> </Vorlage> <Skript> Standard exportieren { Requisiten: ['Start'], berechnet: { Basis () { Rückkehr 42 }, Ergebnis ({ Basis, Start }) { let ergebnis = start für (sei i = 0; i < 1000; i++) { Ergebnis += Math.sqrt(Math.cos(Math.sin(Basis))) + Basis * Basis + Basis + Basis * 2 + Basis * 3 } Ergebnis zurückgeben }, }, } </Skript> Dann rendern wir 300 Komponenten vor und nach der Optimierung der übergeordneten Komponente und lösen die Aktualisierung der Komponenten aus, indem wir die Daten in jedem Frame ändern. Wir öffnen das Chrome Performance-Bedienfeld, um ihre Leistung aufzuzeichnen und erhalten die folgenden Ergebnisse. Vor der Optimierung: Nach der Optimierung: Beim Vergleich dieser beiden Bilder können wir erkennen, dass die Ausführungszeit Der Hauptunterschied besteht hier in der Implementierungsdifferenz des berechneten Warum führt dieser Unterschied also zu Leistungsunterschieden? Der Grund dafür ist, dass jedes Mal, wenn Sie auf Aus Sicht der Nachfrage reicht es aus, wenn Dies ist eine sehr praktische Technik zur Leistungsoptimierung. Denn wenn viele Leute Vue.js-Projekte entwickeln, sind sie es gewohnt, Als ich die Leistung der Tabellenkomponente von ZoomUI optimierte, verwendete ich beim DOM mit v-show wiederverwenden Der vierte Tipp besteht darin, DOM mit Der Komponentencode vor der Optimierung lautet wie folgt: <funktionale Vorlage> <div Klasse="Zelle"> <div v-if="Eigenschaften.Wert" Klasse="ein"> <Schwer :n="10000"/> </div> <Abschnitt v-else Klasse="aus"> <Schwer :n="10000"/> </Abschnitt> </div> </Vorlage> Der optimierte Komponentencode lautet wie folgt: <funktionale Vorlage> <div Klasse="Zelle"> <div v-show="Eigenschaften.Wert" Klasse="ein"> <Schwer :n="10000"/> </div> <Abschnitt v-show="!props.value" Klasse="aus"> <Schwer :n="10000"/> </Abschnitt> </div> </Vorlage> Dann rendern wir 200 Komponenten vor und nach der Optimierung der übergeordneten Komponente und lösen die Aktualisierung der Komponenten aus, indem wir die Daten in jedem Frame ändern. Wir öffnen das Chrome Performance-Bedienfeld, um ihre Leistung aufzuzeichnen und erhalten die folgenden Ergebnisse. Vor der Optimierung: Nach der Optimierung: Beim Vergleich dieser beiden Bilder können wir erkennen, dass die Ausführungszeit Der Hauptunterschied vor und nach der Optimierung besteht darin, dass die Direktive Funktion rendern() { mit(diesem) { return _c('div', { statische Klasse: "Zelle" }, [(Eigenschaften.Wert) ? _c('div', { statische Klasse: „ein“ }, [_c('Schwer', { Attribute: { "n": 10000 } })], 1) : _c('Abschnitt', { statische Klasse: "aus" }, [_c('Schwer', { Attribute: { "n": 10000 } })], 1)]) } } Wenn sich der Wert der Bedingung Daher wird bei Verwendung von Wenn wir die Funktion rendern() { mit(diesem) { return _c('div', { statische Klasse: "Zelle" }, [_c('div', { Anweisungen: [{ Name: "show", Rohname: "v-show", Wert: (Eigenschaften.Wert), Ausdruck: "props.value" }], statische Klasse: „ein“ }, [_c('Schwer', { Attribute: { "n": 10000 } })], 1), _c('Abschnitt', { Anweisungen: [{ Name: "show", Rohname: "v-show", Wert: (!props.value), Ausdruck: "!props.value" }], statische Klasse: "aus" }, [_c('Schwer', { Attribute: { "n": 10000 } })], 1)]) } } Wenn sich der Wert der Bedingung Es stellt sich heraus, dass während des Im Vergleich zu Der Leistungsvorteil von Bei Verwendung von Daher müssen Sie ihre Prinzipien und Unterschiede verstehen, damit Sie in verschiedenen Szenarien entsprechende Anweisungen verwenden können. Am Leben bleiben Der fünfte Tipp besteht darin, die Der Komponentencode vor der Optimierung lautet wie folgt: <Vorlage> <div id="app"> <Router-Ansicht/> </div> </Vorlage> Der optimierte Komponentencode lautet wie folgt: <Vorlage> <div id="app"> <am Leben erhalten> <Router-Ansicht/> </am Leben erhalten> </div> </Vorlage> Wenn wir auf die Schaltfläche klicken, um zwischen der einfachen Seite und der umfangreichen Seite zu wechseln, werden unterschiedliche Ansichten gerendert und das Rendern der umfangreichen Seite ist sehr zeitaufwändig. Wir öffnen das Leistungsfenster von Chrome, um die Leistung aufzuzeichnen, und führen dann die oben genannten Vorgänge vor und nach der Optimierung durch. Dabei erhalten wir die folgenden Ergebnisse. Vor der Optimierung: Nach der Optimierung: Beim Vergleich dieser beiden Bilder können wir erkennen, dass die Ausführungszeit In einem nicht optimierten Szenario wird die Komponente jedes Mal neu gerendert, wenn wir auf eine Schaltfläche klicken, um die Routenansicht zu wechseln. Die gerenderte Komponente durchläuft die Komponenteninitialisierung, Nach der Verwendung Allerdings ist die Verwendung der Zurückgestellte Features Der sechste Tipp besteht darin, Der Komponentencode vor der Optimierung lautet wie folgt: <Vorlage> <div Klasse="aufgeschoben-aus"> <VueIcon icon="fitness_center" class="gigantisch"/> <h2>Ich bin eine schwere Seite</h2> <Schweres v-for="n in 8" :key="n"/> <Schwere Klasse="superschwer" :n="9999999"/> </div> </Vorlage> Der optimierte Komponentencode lautet wie folgt: <Vorlage> <div Klasse="aufgeschoben-am"> <VueIcon icon="fitness_center" class="gigantisch"/> <h2>Ich bin eine schwere Seite</h2> <template v-if="aufschieben(2)"> <Schweres v-for="n in 8" :key="n"/> </Vorlage> <Schwer v-if="defer(3)" class="super-schwer" :n="9999999"/> </div> </Vorlage> <Skript> importiere Defer von '@/mixins/Defer' Standard exportieren { Mixins: Verschieben(), ], } </Skript> Wenn wir auf die Schaltfläche klicken, um zwischen der einfachen Seite und der umfangreichen Seite zu wechseln, werden unterschiedliche Ansichten gerendert und das Rendern der umfangreichen Seite ist sehr zeitaufwändig. Wir öffnen das Leistungsfenster von Chrome, um die Leistung aufzuzeichnen, und führen dann die oben genannten Vorgänge vor und nach der Optimierung durch. Dabei erhalten wir die folgenden Ergebnisse. Vor der Optimierung: Nach der Optimierung: Durch Vergleich dieser beiden Bilder können wir feststellen, dass vor der Optimierung, wenn wir von einer einfachen Seite zu einer umfangreichen Seite wechseln und sich ein Rendering dem Ende nähert, die Seite immer noch als einfache Seite gerendert wird, was den Eindruck einer Seitenverzögerung vermittelt. Wenn wir nach der Optimierung von der einfachen Seite zur umfangreichen Seite wechseln, wird die umfangreiche Seite bereits in einem Rendervorgang am Anfang der Seite gerendert und die umfangreiche Seite wird schrittweise gerendert. Der Unterschied zwischen der Optimierung vor und nach der Optimierung besteht hauptsächlich darin, dass bei letzterer das Standardfunktion exportieren (Anzahl = 10) { zurückkehren { Daten () { zurückkehren { Anzeigepriorität: 0 } }, montiert () { dies.runDisplayPriority() }, Methoden: { runDisplayPriority() { const Schritt = () => { requestAnimationFrame(() => { diese.displayPriority++ wenn (this.displayPriority < Anzahl) { Schritt() } }) } Schritt() }, aufschieben (Priorität) { returniere this.displayPriority >= Priorität } } } } Die Grundidee von Wenn Sie Komponenten haben, deren Rendern Zeit in Anspruch nimmt, empfiehlt es sich, Zeitscheiben Der siebte Tipp ist die Verwendung Der Code vor der Optimierung sieht wie folgt aus: fetchItems ({ commit }, { items }) { commit('Elemente löschen') commit('Artikel hinzufügen', Artikel) } Der optimierte Code lautet wie folgt: fetchItems ({ commit }, { items, splitCount }) { commit('Elemente löschen') const queue = neue JobQueue() splitArray(Elemente, splitCount).fürJeden( chunk => queue.addJob(erledigt => { // Daten in Zeitscheiben übermitteln requestAnimationFrame(() => { commit('Elemente hinzufügen', Block) Erledigt() }) }) ) warte auf Warteschlange.start() } Wir erstellen zunächst 10.000 gefälschte Daten, indem wir auf Vor der Optimierung: Nach der Optimierung: Durch den Vergleich dieser beiden Bilder können wir feststellen, dass die gesamte Warum friert die Seite vor der Optimierung ein? Da zu viele Daten auf einmal übermittelt wurden, war die interne JS-Ausführungszeit zu lang, wodurch der UI-Thread blockiert wurde und die Seite einfror. Nach der Optimierung weist die Seite immer noch einige Verzögerungen auf, da wir die Daten mit einer Granularität von 1.000 Elementen aufgeteilt haben. In diesem Fall besteht immer noch Druck, die Komponenten neu zu rendern. Wir haben festgestellt, dass die fps nur etwa ein Dutzend betrugen, was einige Verzögerungen verursachte. Normalerweise läuft die Seite sehr flüssig, solange die fps der Seite 60 erreichen. Wenn wir die Daten in 100 Teile aufteilen, können die fps grundsätzlich mehr als 50 erreichen. Obwohl das Rendern der Seite flüssiger wird, ist die Gesamtübermittlungszeit für die Fertigstellung von 10.000 Datenteilen immer noch länger. Mithilfe
Nichtreaktive Daten Der achte Tipp besteht darin, Der Code vor der Optimierung sieht wie folgt aus: const Daten = Elemente.Map( Artikel => ({ Ich würde sagen, Daten: Artikel, Abstimmung: 0 }) ) Der optimierte Code lautet wie folgt: const Daten = Elemente.Map( Element => OptimierenElement(Element) ) Funktion optimizeItem (Element) { const itemData = { Ich würde sagen, Abstimmung: 0 } Objekt.defineProperty(itemData, 'data', { // Als nicht reaktiv markieren konfigurierbar: false, Wert: Artikel }) itemData zurückgeben } Wir verwenden immer noch das vorherige Beispiel und erstellen zunächst 10.000 gefälschte Daten, indem wir auf Vor der Optimierung: Nach der Optimierung: Beim Vergleich dieser beiden Bilder können wir erkennen, dass die Ausführungszeit Der Grund für diesen Unterschied liegt darin, dass bei interner Datenübermittlung die neu übermittelten Daten standardmäßig als responsiv definiert werden. Wenn die Unterattribute der Daten in Objektform vorliegen, werden die Unterattribute ebenfalls rekursiv responsiv gemacht. Daher wird dieser Vorgang bei der Übermittlung großer Datenmengen zeitaufwändig. Nach der Optimierung haben wir die Tatsächlich gibt es viele ähnliche Optimierungsmethoden. Beispielsweise müssen einige Daten, die wir in der Komponente definieren, nicht unbedingt in Standard exportieren { erstellt() { this.scroll = null }, montiert() { dies.scroll = neues BScroll(dies.$el) } } Auf diese Weise können wir Virtuelles Scrollen Der neunte Tipp besteht darin, Der Code der Komponente vor der Optimierung lautet wie folgt: <div Klasse="Artikel no-v"> <FetchItemViewFunktional v-for="Artikel von Artikeln" :Schlüssel="Artikel-ID" :Artikel="Artikel" @vote="voteItem(Artikel)" /> </div> Der optimierte Code lautet wie folgt: <Recycling-Scroller Klasse="Artikel" :items="Artikel" :Artikelgröße="24" > <template v-slot="{ Element }"> <Artikelansicht abrufen :Artikel="Artikel" @vote="voteItem(Artikel)" /> </Vorlage> </recycle-scroller> Wir verwenden immer noch das vorherige Beispiel und müssen Vor der Optimierung: Nach der Optimierung: Beim Vergleich dieser beiden Bilder stellen wir fest, dass im nicht optimierten Fall die fps von 10.000 Daten beim Scrollen nur einstellig sind und beim Nicht-Scrollen nur im Dutzend. Der Grund dafür ist, dass im nicht optimierten Szenario zu viele DOMs gerendert werden und das Rendering selbst einem großen Druck ausgesetzt ist. Nach der Optimierung können die fps sogar bei 10.000 Datenelementen im Scroll-Fall über 30 und im Nicht-Scroll-Fall 60 Vollbilder erreichen. Der Grund für diesen Unterschied liegt in der Art und Weise, wie virtuelles Scrollen implementiert wird: Es rendert nur das DOM innerhalb des Ansichtsfensters. Auf diese Weise ist die Gesamtzahl der gerenderten DOMs sehr gering und die Leistung natürlich viel besser. Die virtuelle Scroll-Komponente wurde ebenfalls von Guillaume Chau geschrieben. Interessierte Studierende können sich die Implementierung im Quellcode ansehen. Sein Grundprinzip besteht darin, auf Bildlaufereignisse zu achten, die anzuzeigenden DOM-Elemente dynamisch zu aktualisieren und ihre Verschiebung in der Ansicht zu berechnen. Die virtuelle Bildlaufkomponente ist nicht kostenlos, da sie während des Bildlaufvorgangs in Echtzeit berechnet werden muss, sodass bestimmte Kosten für ZusammenfassenIch hoffe, dass Sie durch diesen Artikel neun Techniken zur Leistungsoptimierung für Vue.js erlernen und diese in tatsächlichen Entwicklungsprojekten anwenden können. Zusätzlich zu den oben genannten Techniken gibt es auch häufig verwendete Methoden zur Leistungsoptimierung, wie z. B. das verzögerte Laden von Bildern, verzögerte Laden von Komponenten, asynchrone Komponenten usw. Bevor wir die Leistung optimieren, müssen wir analysieren, wo der Leistungsengpass liegt, damit wir entsprechende Maßnahmen ergreifen können. Darüber hinaus erfordert die Leistungsoptimierung Datenunterstützung. Bevor Sie eine Leistungsoptimierung durchführen, müssen Sie vor der Optimierung Daten sammeln, damit Sie den Optimierungseffekt durch Datenvergleich nach der Optimierung erkennen können. Ich hoffe, dass Sie sich bei zukünftigen Entwicklungen nicht mehr mit der bloßen Erfüllung von Anforderungen zufrieden geben, sondern beim Schreiben jeder Codezeile auch die möglichen Auswirkungen auf die Leistung berücksichtigen. Verweise[1] vue-9-perf-secrets-Folie: https://slides.com/akryum/vueconfus-2019 [2] gemeinsames Redevideo zu vue-9-perf-secrets: https://www.vuemastery.com/conference/vueconf-us-2019/9-performance-secrets-revealed/ [3] Quellcode des Projekts vue-9-perf-secrets: https://github.com/Akryum/vue-9-perf-secrets [4] vue-9-perf-secrets Online-Demo-Adresse: https://vue-9-perf-secrets.netlify.app/ [5] Diskussionsthema zu vue-9-perf-secrets: https://github.com/Akryum/vue-9-perf-secrets/issues/1 [6] Quellcode des vue-virtual-scroller-Projekts: https://github.com/Akryum/vue-virtual-scroller Damit ist dieser Artikel über neun Tipps zur Leistungsoptimierung für Vue.js (es lohnt sich, ihn zu sammeln) abgeschlossen. Weitere relevante Tipps zur Leistungsoptimierung von Vue.js 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:
|
<<: So prüfen Sie, ob ein Port in LINUX belegt ist
>>: Eine kurze Diskussion über die MySQL-Zeilenanzahl
HTML zum Erreichen eines einfachen ListViews-Effe...
Kobold-Kuh herunterladen CSS-Fussel herunterladen...
Dieser Artikel veranschaulicht anhand von Beispie...
1. Typeinführung 1.1 Domänenbasiertes virtuelles ...
MySQL-Datenbank meldet FEHLER 1045 (28000): Zugri...
Die Implementierung des Erweiterns und Reduzieren...
Wenn Benutzer an einem Backend-Verwaltungssystem ...
Einführung in die Umgebung: Ubuntu Server 16.04.2...
Laden Sie das ZIP-Installationspaket herunter: Do...
Inhaltsverzeichnis 1. Template-Tag in HTML5 2. Ei...
bmi Voyager Heugabel Ulster Lebensmittelhändler F...
Lassen Sie mich Ihnen ohne weitere Umschweife den...
Vorwort Crond ist ein Tool zur geplanten Ausführu...
Wie debuggt man eine Seite auf dem iPad? Wenn Sie ...
Zuerst müssen Sie Vue-cli installieren: npm insta...