Interessante Neuigkeiten Vue 3

Anstelle des Vorworts


Vue wird in allen FunCorp-Projekten verwendet. Wir beobachten die Entwicklung des Frameworks genau, verbessern den Entwicklungsprozess ständig und setzen die Best Practices um. Und natürlich konnten wir den Artikel von Philip Rakovsky, Mitbegründer von VueStorefront, über neue Vue 3-Funktionen, die das Schreiben von Code ernsthaft beeinträchtigen, nicht übersetzten.

Bild
Das letzte Mal haben wir uns Funktionen angesehen, die sich auf die Leistung von Vue 3 auswirken. Wir wissen bereits, dass auf der neuen Version des Frameworks geschriebene Anwendungen sehr schnell funktionieren, aber die Leistung ist nicht die wichtigste Änderung. Für die meisten Entwickler ist es viel wichtiger, wie sich Vue 3 auf die Art und Weise auswirkt, wie Sie Code schreiben.

Wie Sie vielleicht erraten haben, wird Vue 3 viele coole Funktionen haben. Glücklicherweise hat das Vue-Team mehr Verbesserungen und Ergänzungen vorgenommen als Änderungen. Aus diesem Grund sollten sich die meisten Entwickler, die Vue 2 kennen, schnell mit der neuen Syntax vertraut machen.

Beginnen wir mit einer API, von der viele von Ihnen vielleicht schon gehört haben.

Kompositions-API


Die Composition-API ist das am häufigsten diskutierte und am häufigsten erwähnte Feature der nächsten Hauptversion von Vue. Die Composition-API-Syntax bietet einen völlig neuen Ansatz zum Organisieren und Wiederverwenden von Code.

Wir erstellen jetzt Komponenten mit einer Syntax namens Options API. Um Logik hinzuzufügen, erstellen wir im Komponentenobjekt Eigenschaften (Optionen), z. B. Daten, Methoden, berechnete usw. Der Hauptnachteil dieses Ansatzes besteht darin, dass es sich nicht um JavaScript-Code als solchen handelt. Sie müssen genau wissen, welche Optionen in der Vorlage verfügbar sind und wie diese aussehen werden. Der Vue-Compiler konvertiert Eigenschaften für Sie in funktionierenden JavaScript-Code. Aufgrund dieser Funktion können wir die automatische Vervollständigung oder die Typprüfung nicht vollständig verwenden.

Die Composition-API löst dieses Problem und ermöglicht die Verwendung der in den Optionen verfügbaren Mechanismen mit normalen JavaScript-Funktionen.
Das Vue-Team beschreibt die Kompositions-API als "optionale, funktionsbasierte API, die eine flexible Verwendung der Komposition in der Komponentenlogik ermöglicht". Code, der mit der neuen API geschrieben wurde, ist einfacher zu lesen und somit verständlicher.

Um zu verstehen, wie die neue Syntax funktioniert, betrachten Sie ein Beispiel für eine einfache Komponente.

<template> <button @click="increment"> Count is: {{ count }}, double is {{ double }}, click to increment. </button> </template> <script> import { ref, computed, onMounted } from 'vue' export default { setup() { const count = ref(0) const double = computed(() => count.value * 2) function increment() { count.value++ } onMounted(() => console.log('component mounted!')) return { count, double, increment } } } </script> 

Wir werden den Code in Teile zerlegen und analysieren, was hier passiert.

 import { ref, computed, onMounted } from 'vue' 

Wie oben erwähnt, stellt die Composition-API die Komponentenoptionen als Funktionen dar. Daher müssen zunächst die erforderlichen Funktionen importiert werden. In diesem Beispiel müssen wir eine reaktive Eigenschaft mit ref erstellen, die mit computed berechnet wurde, und mit der Funktion onMounted auf den eingehängten Lifecycle-Hook zugreifen.

Möglicherweise haben Sie eine Frage: Was ist diese mysteriöse Einrichtungsmethode?

 export default { setup() {} } 

Kurz gesagt, Setup ist nur eine Funktion, die Eigenschaften und Funktionen an eine Vorlage übergibt. Wir beschreiben alle reaktiven und berechneten Eigenschaften, Lifecycle-Hooks und alle Beobachter in der Setup-Funktion und geben sie zur Verwendung in der Vorlage zurück.

Damit wir nicht vom Setup zurückkehren, gibt es keinen Zugriff in der Vorlage.

 const count = ref(0) 

Die zählreaktive Eigenschaft wird mit der Funktion ref initialisiert. Es nimmt ein Primitiv oder Objekt und gibt eine reaktive Verknüpfung zurück. Der übergebene Wert wird in der value-Eigenschaft des erstellten Links gespeichert. Wenn wir beispielsweise auf den Wert von count zugreifen möchten, müssen wir explizit auf count.value zugreifen.

 const double = computed(() => count.value * 2) function increment() { count.value++ } 

Wir deklarieren also eine berechnete Double-Eigenschaft und eine Inkrement-Funktion.

 onMounted(() => console.log('component mounted!')) 

Mit dem onMounted-Hook drucken wir nach dem Mounten der Komponente eine Nachricht an die Konsole, um diese Möglichkeit zu demonstrieren.

 return { count, double, increment } 

Damit die count- und double-Eigenschaften und die increment-Methode in der Vorlage verfügbar sind, geben wir sie von der setup-Methode zurück.

 <template> <button @click="increment"> Count is: {{ count }}, double is {{ double }}. Click to increment. </button> </template> 

Und voila! Wir haben vom Setup aus Zugriff auf die Eigenschaften und Methoden, als ob sie über die alte Options-API deklariert worden wären.

Dies ist ein einfaches Beispiel. Ähnliches könnte leicht mit der Options-API geschrieben werden.
Der Vorteil der neuen Composition-API liegt jedoch nicht in der Möglichkeit, Code in einem anderen Stil zu schreiben, sondern in den Möglichkeiten, die sich für die Wiederverwendung von Logik eröffnen.

Wiederverwenden von Code mit der Composition-API


Schauen wir uns die Vorteile der neuen Composition-API genauer an, zum Beispiel für die Wiederverwendung von Code. Wenn wir nun einen Teil des Codes in mehreren Komponenten verwenden möchten, haben wir zwei Möglichkeiten: Mixins und Scoped Slots. Beide Optionen haben ihre Nachteile.

Wir möchten die Funktionalität des Zählers extrahieren und in anderen Komponenten wiederverwenden. Hier ist ein Beispiel, wie dies unter Verwendung der vorhandenen und der neuen API durchgeführt werden kann.

Betrachten Sie zunächst die Implementierung mit Mixins.

 import CounterMixin from './mixins/counter' export default { mixins: [CounterMixin] } 

Das größte Problem bei diesem Ansatz ist, dass wir nichts darüber wissen, was zu unserer Komponente hinzugefügt wird. Dies erschwert das Verständnis und kann zu Konflikten mit vorhandenen Eigenschaften und Methoden führen.

Betrachten Sie nun Slots mit einem begrenzten Umfang.

 <template> <Counter v-slot="{ count, increment }"> {{ count }} <button @click="increment">Increment</button> </Counter> </template> 

Bei der Verwendung von Slots wissen wir genau, auf welche Eigenschaften wir über die v-slot-Direktive zugreifen können, was recht einfach zu verstehen ist. Der Nachteil dieses Ansatzes ist, dass wir nur auf die Daten der Counter-Komponente zugreifen können.

Betrachten Sie nun eine Implementierung mit der Composition-API.

 function useCounter() { const count = ref(0) function increment () { count.value++ } return { count, incrememt } } export default { setup () { const { count, increment } = useCounter() return { count, increment } } } 

Es sieht viel eleganter aus, oder? Wir sind weder an eine Vorlage noch an einen Bereich gebunden und wissen genau, welche Zählereigenschaften verfügbar sind. Und da useCounter nur eine Funktion ist, die Daten zurückgibt, erhalten wir als angenehmen Bonus die Code-Vervollständigung im Editor. Hier gibt es keine Magie, daher kann uns der Editor bei der Typprüfung helfen und Hinweise geben.

Die Verwendung von Bibliotheken von Drittanbietern sieht ebenfalls besser aus. Wenn wir beispielsweise Vuex verwenden möchten, können wir die useStore-Funktion explizit importieren und den Vue-Prototyp damit nicht verstopfen. $ Store-Eigenschaft. Dieser Ansatz ermöglicht es Ihnen, zusätzliche Manipulationen in Plugins zu beseitigen.

 const { commit, dispatch } = useStore() 

Wenn Sie mehr über die Composition-API und ihre Anwendungen erfahren möchten, empfehle ich, ein Dokument zu lesen, in dem das Vue-Team die Gründe für die Erstellung einer neuen API erläutert und Fälle aufzeigt, in denen dies hilfreich sein wird. Es gibt auch ein wunderbares Repository mit Beispielen für die Verwendung der Kompositions-API von Thorsten Lünborg, einem Mitglied des Vue-Kernteams.

Konfigurations- und Montageänderungen


In der neuen Version gibt es weitere wichtige Änderungen in der Art und Weise, wie wir unsere Anwendung erstellen und konfigurieren. Schauen wir uns ein Beispiel an.

 import Vue from 'vue' import App from './App.vue' Vue.config.ignoredElements = [/^app-/] Vue.use(/* ... */) Vue.mixin(/* ... */) Vue.component(/* ... */) Vue.directive(/* ... */) new Vue({ render: h => h(App) }).$mount('#app') 

Wir verwenden jetzt das globale Vue-Objekt, um neue Vue-Instanzen zu konfigurieren und zu erstellen. Jede Änderung, die wir am Vue-Objekt vornehmen, wirkt sich auf die endgültigen Instanzen und Komponenten aus.

Mal sehen, wie das in Vue 3 funktioniert.

 import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.config.ignoredElements = [/^app-/] app.use(/* ... */) app.mixin(/* ... */) app.component(/* ... */) app.directive(/* ... */) app.mount('#app') 

Wie Sie bereits bemerkt haben, bezieht sich die Konfiguration auf eine bestimmte Vue-Instanz, die mit createApp erstellt wurde.

Dies macht unseren Code lesbarer und verringert die Möglichkeit unerwarteter Probleme mit Plugins von Drittanbietern. Jetzt kann sich jede Bibliothek eines Drittanbieters, die das globale Vue-Objekt ändert, auf Ihre Anwendung an einem unerwarteten Ort auswirken (insbesondere, wenn es sich um ein globales Mixin handelt), was in Vue 3 nicht möglich ist.

Diese Änderungen werden im RFC besprochen , und möglicherweise wird die Implementierung in Zukunft anders sein.

Fragmente


Ein weiteres cooles Feature, auf das wir in Vue 3 zählen können.
Was sind Fragmente?
Derzeit kann eine Komponente nur ein Stammelement haben, was bedeutet, dass der folgende Code nicht funktioniert.

 <template> <div>Hello</div> <div>World</div> </template> 

Der Grund dafür ist, dass die Vue-Instanz, die sich hinter jeder Komponente versteckt, nur einem DOM-Element zugeordnet werden kann. Jetzt gibt es eine Möglichkeit, eine Komponente mit mehreren Stammelementen zu erstellen: Dazu müssen Sie eine Komponente in einem funktionalen Stil schreiben, der keine eigene Vue-Instanz benötigt.

Es stellt sich heraus, dass das gleiche Problem in der React-Community besteht, das mit dem virtuellen Fragment-Element behoben wurde.

Es sieht so aus:

 class Columns extends React.Component { render() { return ( <React.Fragment> <td>Hello</td> <td>World</td> </React.Fragment> ); } } 

Obwohl Fragment wie ein reguläres DOM-Element aussieht, ist es virtuell und wird nicht in der DOM-Struktur erstellt. Mit diesem Ansatz können wir die Funktionalität eines einzelnen Stammelements nutzen, ohne ein zusätzliches Element im DOM zu erstellen.

Jetzt können Sie Fragmente in Vue 2 verwenden, aber mit der Vue-Fragmentbibliothek, und in Vue 3 funktionieren sie sofort!

Spannung


Eine weitere großartige Idee aus dem React-Ökosystem, die in Vue 3 implementiert wird, ist Suspense.

Mit Suspense wird das Rendern von Komponenten angehalten und ein Stub angezeigt, bis bestimmte Bedingungen erfüllt sind. Bei Vue London berührte Ewan Yu beiläufig Suspense und enthüllte die API, die wir in Zukunft erwarten können. Die Suspense-Komponente verfügt über zwei Steckplätze: für Inhalte und für Stubs.

 <Suspense> <template > <Suspended-component /> </template> <template #fallback> Loading... </template> </Suspense> 

Der Stub wird angezeigt, bis die Komponente <Suspended-component /> bereit ist. Die Suspense-Komponente erwartet möglicherweise auch, dass sie die asynchrone Komponente lädt oder einige asynchrone Aktionen in der Setup-Funktion ausführt.

Mehrere V-Modelle


v-model ist eine Direktive, mit der Sie die bidirektionale Bindung verwenden können. Wir können die reaktive Eigenschaft übergeben und sie innerhalb des Bauteils ändern.

Wir sind bekannt für die Arbeit mit Formularelementen.

 <input v-model="property" /> 

Aber wussten Sie, dass V-Modell mit jeder Komponente verwendet werden kann? Unter der Haube leitet das V-Modell lediglich den Werteparameter weiter und wartet auf das Eingabeereignis.

Sie können das vorherige Beispiel mit dieser Syntax wie folgt umschreiben:

 <input v-bind:value="property" v-on:input="property = $event.target.value" /> 

Sie können sogar die Standardeigenschaftsnamen und -ereignisse mithilfe der Modelloption ändern:

 model: { prop: 'checked', event: 'change' } 

Wie Sie sehen, kann die v-model-Direktive ein sehr nützlicher „syntaktischer Zucker“ sein, wenn wir in unseren Komponenten die bidirektionale Bindung verwenden möchten. Leider kann es nur ein V-Modell pro Komponente geben.

Zum Glück wird dieses Problem in Vue 3 behoben. Wir können den Namen an v-model übergeben und so viel v-model wie nötig verwenden.

Anwendungsbeispiel:

 <InviteeForm v-model:name="inviteeName" v-model:email="inviteeEmail" /> 

Diese Änderungen werden im RFC besprochen , und möglicherweise wird die Implementierung in Zukunft anders sein.

Portale


Portale sind Komponenten, die zum Rendern von Inhalten außerhalb der Hierarchie der aktuellen Komponente erstellt wurden. Dies ist auch eine der in React implementierten Funktionen. In der React-Dokumentation werden Portale wie folgt beschrieben: "Mithilfe von Portalen können Sie untergeordnete Elemente in einem DOM-Knoten rendern, der sich außerhalb der DOM-Hierarchie der übergeordneten Komponente befindet."

Portale eignen sich hervorragend zum Implementieren von Komponenten wie modalen Fenstern, Popups und allen anderen, die oben auf der Seite angezeigt werden müssen.

Wenn Sie Portale verwenden, können Sie sicher sein, dass sich die Stile der übergeordneten Komponente nicht auf die untergeordnete Komponente auswirken. Es erspart Ihnen auch schmutzige Z-Index-Hacks.

Für jedes Portal müssen wir das Ziel angeben, in dem der Portalinhalt angezeigt werden soll.

Das Folgende ist eine Implementierungsoption für die Portal-Vue-Bibliothek, mit der Portale zu Vue 2 hinzugefügt werden.

 <portal to="destination"> <p>This slot content will be rendered wherever the portal-target with name 'destination' is located.</p> </portal> <portal-target name="destination"> <!-- This component can be located anywhere in your App. The slot content of the above portal component wilbe rendered here. --> </portal-target> 

In Vue 3 ist diese Funktion sofort einsatzbereit.

Neue API für benutzerdefinierte Richtlinien


Die benutzerdefinierte Direktiven-API wird in Vue 3 etwas geändert, um dem Lebenszyklus der Komponente besser zu entsprechen. Das Erstellen von Anweisungen wird intuitiver und daher für Anfänger einfacher zu verstehen und zu lernen.

Nun sieht die Deklaration der user-Direktive so aus:

 const MyDirective = { bind(el, binding, vnode, prevVnode) {}, inserted() {}, update() {}, componentUpdated() {}, unbind() {} } 

Und in Vue 3 wird es so aussehen:

 const MyDirective = { beforeMount(el, binding, vnode, prevVnode) {}, mounted() {}, beforeUpdate() {}, updated() {}, beforeUnmount() {}, // new unmounted() {} } 

Obwohl dies wichtige Änderungen sind, können sie mit einem kompatiblen Vue-Build verwendet werden.

Diese API wird ebenfalls diskutiert und kann sich in Zukunft ändern.

Zusammenfassung


Neben der bedeutenden Innovation - der Composition API - finden wir einige kleinere Verbesserungen. Offensichtlich ist Vue bestrebt, die Entwicklererfahrung zu verbessern und intuitive APIs zu vereinfachen. Es ist auch schön zu sehen, dass das Vue-Team beschlossen hat, dem Kern des Frameworks viele Ideen hinzuzufügen, die bereits in Bibliotheken von Drittanbietern implementiert sind.

Die obige Liste enthält nur die wichtigsten Verbesserungen und Änderungen an der API. Wenn Sie mehr über andere erfahren möchten, lesen Sie das RFC-Repository .

Source: https://habr.com/ru/post/de475968/


All Articles