Dein erstes Composable
Komponenten wachsen. In der Lektion Lebenszyklus und Daten brauchte das Laden der Speisekarte drei Refs und ein onMounted, und jede andere Komponente, die etwas lädt, bräuchte dieselben Zeilen noch einmal. Vues Antwort ist ein Composable: eine Funktion, die ref, computed, watch oder Lifecycle-Hooks von Vue benutzt und zurückgibt, was eine Komponente braucht. Ihr Name beginnt mit use, damit man sie erkennt: useZaehler, useLocalStorage, useFetch.
Hier ist ein Zähler als Composable. Er steht in einer eigenen Datei, useZaehler.js:
import { ref } from "vue";
export function useZaehler(start) {
const anzahl = ref(start);
function erhoehen() {
anzahl.value++;
}
return { anzahl, erhoehen };
}Und hier ist eine Komponente, die ihn benutzt:
<script setup>
import { useZaehler } from "./useZaehler.js";
const { anzahl, erhoehen } = useZaehler(0);
</script>
<template>
<p>Tassen Kaffee heute: {{ anzahl }}</p>
<button @click="erhoehen">+1 Tasse</button>
</template>Das ist neu:
- Ein Composable steht in einer
.js-Datei, nicht in einer.vue-Datei: Es hat keine Vorlage und keine Styles, nur JavaScript. Es importiert aus"vue", was es braucht. export functionexportiert die Funktion unter ihrem Namen, so wieexport constin der Lektion Komponenten. Die Komponente importiert sie also in geschweiften Klammern, so wie sierefaus"vue"importiert:import { useZaehler } from "./useZaehler.js";.- Die Komponente ruft das Composable oben im
<script setup>auf, wie sieref()aufruft. Das Composable erstellt dann den Ref und die Funktion und gibt sie in einem Objekt zurück, und die Destrukturierung holt sie heraus:const { anzahl, erhoehen } = useZaehler(0);. - Von da an funktionieren
anzahlunderhoehen, als hätte man sie in der Komponente selbst geschrieben:anzahlist ein Ref, den{{ anzahl }}zeigt, underhoehenist eine Funktion für@click.
Jeder Aufruf erstellt einen neuen Ref: Zwei Komponenten, die useZaehler() aufrufen, haben jede ihre eigene anzahl. Ein Composable aufzurufen ist, als würdest du seine Zeilen in die Komponente kopieren, nur dass sie nur einmal geschrieben sind.
Typische Fehler:
import useZaehler from "./useZaehler.js";ohne die Klammern: Das importiert den Default-Export der Datei, den es nicht gibt. Die Seite bleibt leer, mit einemTypeErrorin der Konsole.returnvergessen: Die Funktion gibt dannundefinedzurück, und die Destrukturierung endet mit einemTypeError, der mitCannot destructure property 'anzahl'beginnt.
So schreibst du es:
Anweisungen
- 1
Verschiebe den Zähler in ein Composable. Schreibe in
useZaehler.jsuseZaehler(start)wie oben. Importiere es inApp.vueund ersetze den Ref und die Funktion durchconst { anzahl, erhoehen } = useZaehler(0);. Die Seite funktioniert wie vorher. - 2
Füge dem Composable eine Funktion
zuruecksetzen()hinzu, dieanzahlaufstartzurücksetzt, die Zahl, mit der der Zähler begonnen hat, und gib sie auch zurück. Hole sie inApp.vuezusammen mit den anderen heraus und füge nach+1 Tasseeinen ButtonZurücksetzenhinzu, der sie aufruft.