Vue.js 3: Reactivity System und Composition API unter der Lupe

Version 3 bringt Neues für das Web-Framework, darunter die Composition API und die Änderungen am Reactivity-System. Ein Blick auf Vue.js 3 lohnt sich.

In Pocket speichern vorlesen Druckansicht 6 Kommentare lesen

(Bild: Trismegist san/Shutterstock.com)

Lesezeit: 22 Min.
Von
  • Dr. Fabian Deitelhoff
Inhaltsverzeichnis

Beim Web-Framework Vue.js stehen einige Änderungen und Neuerungen an. Das zeigte bereits der erste im Dezember 2020 veröffentlichte Teil des Artikels. Der Vue.js 3 Core wird jetzt seit circa fünf Monaten als stabil eingestuft und in der Community intensiv diskutiert. Für den Core bleibt aber vorerst das Repository vue-next auf GitHub bestehen, bis Version 3 vollständig veröffentlicht wird und das Repository mit Version 2 ersetzen kann. Das Angebot rund um Vue.js wächst ebenfalls, beispielsweise die offizielle Dokumentation, Bibliotheken, Videokurse und Ähnliches. Der Buchmarkt ist bisher noch schwach aufgestellt, was sich aber kurzfristig ändern dürfte.

In der Zwischenzeit ist die Entwicklung am Framework fleißig vorangeschritten. Vollständig veröffentlicht ist Vue 3 im April 2021 noch nicht. Insbesondere sind für das Ökosystem noch zahlreiche Anpassungen und neue Versionen zu erwarten. Vue.js 3 kann aber dennoch bereits jetzt zum Einsatz kommen. Einige Bibliotheken wie Vue CLI, Vue Router und Vuex bringen bereits Unterstützung für das Web-Framework mit – wenn auch noch nicht final.

Während der erste Artikel eine allgemeine Übersicht der Überarbeitungen und Neuerungen bot, geht es nun um drei ganz konkrete Änderungen. Die erste betrifft das globale Mounting, wodurch Anwendungen anders initialisiert werden müssen. Diese Anpassungen hat der erste Artikel bereits angeschnitten, sie führen aber immer wieder zu Stirnrunzeln und werden daher auch in diesem Artikel im Zuge der Vorstellung eines Demoprojektes mit Vue.js 3 noch einmal kurz aufgegriffen. Zwei umfangreichste Anpassungen betreffen das Reactivity-System und die Composition API. Beide sollen im Rahmen dieses Artikels anhand eines Demoprojekts im Detail vorgestellt werden.

An der schrittweisen Veröffentlichungsstrategie von Vue 3 hat sich bisher nichts geändert. Das Core-Projekt von Vue.js ist veröffentlicht und das Ökosystem weitgehend kompatibel. An einem dedizierten Migrations-Build wird aber weiterhin gearbeitet. Dieses Build von Vue.js 3 soll Vue.js-2-kompatible Verhaltensweisen und Laufzeitwarnungen enthalten, wenn inkompatible Funktionen genutzt werden. Damit lassen sich nicht-triviale Anwendungen einfacher migrieren. Das Core-Team hat dazu ein offizielles Statement abgegeben, dass für umfangreiche Migrationen auf diesen Build gewartet werden soll.

Die Stimmung in der Community scheint sich bisher nicht großartig verändert zu haben. Die meisten Blogposts und Meinungen drehen sich um die Composition API, den Release-Prozess an sich und den typischen Vergleich mit anderen Frameworks. Ein vollständiges Bild ergibt sich daher erst, wenn Vue.js 3 und das Ökosystem vollständig umgestellt sind, und wenn der Migration Build vorhanden ist, sodass sich größere Anwendungen umstellen lassen. Das ist sicherlich ein kritischer Punkt, an dem sich Vue.js 3 bewähren muss.

Auch bei Vue.js 3 empfiehlt es sich, ein neues Projekt über das CLI anzulegen. In diesem Artikel kommt Version 4.5.11 des mit yarn global installierten Kommandozeilen-Tools zum Einsatz. Abbildung 1 zeigt, das Vue 3 weiterhin als Preview markiert ist. Bei der manuellen Auswahl der Funktionen sind wie üblich TypeScript, Vue Router, Vuex und CSS-Präprozessoren auswählbar. Wer hier Vue.js 3 auswählt, kann anschließend nur noch die Class-Style Components wählen oder weglassen. Die restlichen Optionen beim Anlegen eines Projektes der CLI bieten die üblichen und bekannten Möglichkeiten aus den Vorversionen an – beispielsweise für die Auswahl externer Komponenten wie Vue Route und Vuex oder die Auswahl von Linter beziehungsweise Formatter.

Die Auswahlmöglichkeiten beim Vue CLI (Abb. 1)

Die Composition API gilt lediglich als Option, denn sie steht beim Aufsetzen eines Projekts nicht zur Auswahl. Das ist genauso, wenn bei der Übersicht der Optionen nicht TypeScript ausgewählt wird, sodass nur die klassische Options API statt der Class-based Component-Syntax nicht zur Verfügung steht. Dann gibt es nur die klassische Options API. In diesem Stil werden alle Komponenten erzeugt. Es ist zu hoffen, dass die Composition API als eigenständige Option beim Erzeugen eines Projekts angeboten wird.

Die neue Vue-App wird, je nach ausgewählten Plug-ins, gemäß dem neuen global Mounting erzeugt, wie die beiden folgenden Codeausschnitte zeigen. Der erste zeigt den einfachsten Fall, wenn nur die Anwendung erstellt wird:

import { createApp } from "vue";
import App from "./App.vue";

createApp(App).mount("#app");

Im zweiten Fall kommen zusätzliche Plug-ins wie der Vuex Store und der Vue Router hinzu:

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";

createApp(App)
  .use(store)
  .use(router)
  .mount("#app");

Das trägt zur Lesbarkeit bei und verdeutlicht auf wenigen Zeilen, was bei der aktuellen App-Instanz zum Einsatz kommt und was nicht. Dieses neue, globale Mounting hat zudem Auswirkungen auf andere Komponenten oder Plug-ins, die bei der globalen Vue.js-Instanz registriert werden sollen. Eine globale Komponente ist nun wie folgt zu registrieren:

import MyComponent from './components/MyComponent ';
app.component('MyComponent', MyComponent);

Das vorherige Codebeispiel nutzt die Methode use bereits, um Plug-ins global zu registrieren. Das funktioniert bei eigenen Plug-ins ebenso:

import myPlugin from './plugins/myPlugin';
const options = …
createApp(App)
    .use(myPlugin, options);

Was für Komponenten und Plug-ins funktioniert, lässt sich über die Methoden mixin und directive für Mixins sowie Direktiven ebenfalls nutzen. Der folgende Codeausschnitt zeigt das am Beispiel eines Mixins:

createApp(App)
  .mixin({
    created() {
      console.log("created in mixin");
    }
  })
  .mount("#app");