byteleaf logo
← zurück zum Blog

Vue Composition API

Vue.js ist momentan, neben React und Angular, eines der drei großen Frontend-Frameworks. Die kürzlich erschienene Version 3 bietet mit der Composition API einen neuen funktionalen Weg, um Teile von Komponenten noch modularer und wiederverwendbarer zu gestalten.
Paul Tolstoi
Paul Tolstoi
12. April 2021

Einführung in Vue.js

Seit einigen Jahren lassen sich Webanwendungen nicht mehr aus dem Alltag wegdenken. Die Fülle an Funktionalitäten, die manch eine Anwendung bietet, lässt sich durch ein Frontend-Framework einfacher abstrahieren. Die wohl bekanntesten und meistverbreiteten Vertreter dieser Frameworks sind React und Angular; es gibt aber auch andere weniger populäre auf dem Gebiet. Eines solcher Frameworks ist Vue.js, dass am 18. September 2020 in der Version 3.0 erschienen ist.

Vue ist vom ehemaligen Google-Mitarbeiter Evan You entwickelt worden und ist von AngularJS inspiriert. Es ist ein leichtgewichtiges Komponenten-basiertes Frontend-Framework, das neben Rendering auch ein reaktives State-Management mit sich bringt.

Grundsätzlich besteht eine Komponente aus drei optionalen Teilen:

  • template: umfasst das Markup, welches von Vue.js beim Rendern der Komponente verwendet wird
  • script: beinhaltet den Code, der die Komponente mit Leben erfüllt
  • style: enthält für die Komponente relevantes Styling

Hier ein kleines Beispiel einer einfachen Zähler-Komponente:

1<template>
2  <p>{{ formattedCount }}</p>
3
4  <button @click="increase">+1</button>
5  <button @click="increaseSlightly">+0.1</button>
6</template>
7
8<script lang="ts">
9  import { defineComponent } from "vue";
10
11  export default defineComponent({
12    name: "CounterVue1Style",
13    data() {
14      return { count: 0 };
15    },
16    methods: {
17      increase() {
18        this.count++;
19      },
20      increaseSlightly() {
21        this.count += 0.1;
22      },
23    },
24    computed: {
25      formattedCount() {
26        return this.count.toFixed(1);
27      },
28    },
29  });
30</script>

Die Komponente hat einen internen State: count: 0 und zwei Methoden um diesen State zu verändern: increase erhöht den count um 1; sowie increaseSlightly, welches den count um 0.1 erhöht. Außerdem gibt es eine sogenannte Computed Property formattedCount: Sie formatiert unseren count als Zahl mit einer Nachkommastelle. Eine Computed Property -wie der Name schon sagt- berechnet einen Zwischenwert, der mehrmals wiederverwendet werden kann. Nur wenn sich ein zur Berechnung verwendeter reaktiver Wert (z. B. der State) ändert, dann wird auch die Computed Property neu berechnet.

Das Markup, welches von der Komponente generiert wird, zeigt den formatierten count an und bietet zwei Knöpfe um den Zähler jeweils um +1 oder +0.1 zu erhöhen. Die Komponente besitzt kein gesondertes Styling.

Diese Art Komponente zu definieren, stammt noch aus der Zeit von Vue.js 1, und hat einige Schwachstellen. Das this in den Methoden und Computed Properties beziehen sich auf die Komponente selbst und nicht auf das jeweils umgebende Objekt. Kontextwechsel führen nicht nur bei nicht-Vue.js-Entwicklern zu einer kognitive Belastung, sondern bereiten auch manchen Entwicklungsumgebungen Probleme, da sie mit dem Typing nicht zurecht kommen.

Vor allem bei größeren Komponenten führt diese Art Komponentenerstellung dazu, dass der Code nicht nach Funktionalitäten, sondern nach dem Typ, sortiert ist. Anstatt, dass sich alle Funktionen, die sich z. B. mit der Datenbeschaffung und Weiterverarbeitung beschäftigen, zusammen an einem Ort befinden, werden diese nach ihrem Typ sortiert: alle Methoden zusammen, alle Computed Properties zusammen, und so weiter. Man muss also jedes Mal im Code springen und suchen, wo welche Funktion definiert ist.

In dieser Form lässt sich die Funktionalität der Komponente auch in keiner anderen Komponente wiederverwenden (man denke auch hier an das Laden von Daten nach dem Prinzip stale-while-revalidate (SWR)), da sowohl der State als auch die zugehörigen Methoden und Computed Properties fest an die Komponente gebunden sind.

Um unter anderem auch diese Punkte zu verbessern, ist mit der Version 3 des Frameworks eine zusätzliche Möglichkeit hinzukommen, wie man Teile von Komponenten noch modularer und wiederverwendbarer gestalten kann: Die Composition API. Auch für die v2 von Vue.js gibt es ein extra Package, womit die neue API auch in älteren Anwendungen genutzt werden kann.

Die Composition API

Die Composition API ist stark von React Hooks inspiriert und ist der Versuch diese für die Vue.js-Welt zu adaptieren. Die Idee hinter der API ist simpel: Zusammenhängende Funktionalitäten sollen in eigene "Composition Functions" extrahiert werden, damit diese in mehreren Komponenten wiederverwendet werden können. Jede Komponente wird am Ende also nur aus solchen Funktionen zusammengesetzt und muss keine weitere Logik beinhalten. Da es sich am Ende nur um Funktionen und nicht um geschachtelten Objekte handelt, vereinfacht sich auch die Typisierung des Ganzen, was auch IDEs die Arbeit vereinfacht, um die korrekten Typen herzuleiten.

Aus der Zähler-Komponente, die wir vorher definiert haben, können wir zum Beispiel folgende Composition-Funktion extrahieren:

1import { reactive, computed } from "vue";
2
3const useCounter = () => {
4  const state = reactive({ count: 0 });
5
6  return {
7    count: computed(() => state.count),
8    increase: () => state.count++,
9    increaseSlightly: () => (state.count += 0.1),
10    formattedCount: computed(() => state.count.toFixed(1)),
11  };
12};

Die Funktionalität und Benennung der Methoden und Computed Properties behalten wir bei. Eine Composition-Funktion besteht selbst wiederum aus anderen Composition-Funktionen:

  • reactive macht ein Objekt reaktiv. Jedes Mal, wenn im Code auf das Objekt oder eines der Felder zugegriffen wird, merkt sich Vue.js diese Abhängigkeit und rendert bei Änderungen die Komponente bzw. nur die betroffenen Teile neu.
  • computed verhält sich wie eine Computed Property.

Als Rückgabewert einer Composition-Funktion geben wir alle Methoden und reaktiven Werte und Objekte zurück, die wir der verwenden Funktion zur Verfügung stellen wollen.

Diese Composition-Funktion kann jetzt in einer einfachen Komponente verwendet werden. Das Template der Komponente ändert sich in diesem Fall nicht:

1<script lang="ts">
2  import { defineComponent } from "vue";
3  import { useCounter } from "./counter";
4
5  export default defineComponent({
6    name: "CounterWithCompositionAPI",
7    setup() {
8      return {
9        ...useCounter(),
10      };
11    },
12  });
13</script>

Wer die Composition API verwenden will, muss den neuen Einstiegspunkt setup verwenden. Diese Funktion wird einmalig beim Erstellen der Komponente aufgerufen und sollte ein Objekt mit allen reaktiven Werten sowie Methoden zurückgeben, die dem Template zur Verfügung gestellt werden sollen. Alle Veränderungen werden anschließend über das reaktive System von Vue.js automatisch aufgelöst.

Fazit

Funktionalitäten, die sich früher kaum oder sehr aufwendig (z. B. durch Mixins) wiederverwendet haben lassen, können mit der Composition API ziemlich einfach extrahiert und in mehreren Komponenten nach belieben wieder kombiniert werden. Wie bei den React Hooks, die einiges an Veränderungen ins Ökosystem mit sich brachten, ist ein ähnlicher Trend auch mit der Composition API bei Vue.js zu erwarten.

Kontakt

E-Mail

info@byteleaf.de

Telefon

+49 89 90183650

Links

Code

GitHub

Wo wir sind

Adresse

byteleaf GmbH
Adamstraße 5
80636 München

ImpressumDatenschutzCookie-Einstellungen
© 2021 - Code: byteleaf - Design: Michael Motzek