Dependency Injection mit Vue

Wer mit Spring Boot arbeitet, kommt um Dependency Injection nicht herum. Dabei lädt Spring alle Abhängigkeiten in den Spring Context, und diese Abhängigkeiten können dann durch Parameter im Konstruktor geladen werden. Dieses Prinzip hat den großen Vorteil, dass alle Abhängigkeiten klar erkennbar sind und diese Klassen einfach getestet werden können. Alle Abhängigkeiten können auch im Laufe der Entwicklung ausgetauscht werden.

Dieses Verhalten ist im Backend nichts Neues und wird auch in vielen TypeScript-basierten Frameworks genutzt, wie zum Beispiel in Angular oder nest.js. Mit der Vue 3 Composition API können wir jedoch die Klassenkonstruktoren nicht nutzen, da diese Komponenten keine Klassen besitzen.

Vue bietet jedoch die Möglichkeit, Dinge mit den Methoden „provide“ und „inject“ zu transportieren. Damit lässt sich ein Dependency Injection Prinzip sehr einfach nachbauen. Die Methodensignatur von „provide“ ist folgendermaßen:

provide<T>(key: InjectionKey<T> | string, value: T): this;

Das bedeutet, wir können einen String oder einen InjectionKey übergeben. Da wir einen konkreten Typ nutzen wollen, werden wir den InjectionKey verwenden. Jede Klasse, die wir in unseren „Context“ laden wollen, registrieren wir in der „main.ts“ durch die Verkettung von „provide“-Aufrufen. Dabei ist zu beachten, dass wir ein „Key“-Objekt erzeugen müssen. Analog zu Spring sind alle unsere Serviceklassen Singletons und werden nur einmal initialisiert. Unsere erstellte Serviceklasse sieht dann so aus:

export class NiceService {
}

export const NiceServiceKey: InjectionKey<NiceService> = Symbol('NiceService');

Die Serviceklasse können wir nun nach Belieben implementieren, während wir die Keyklasse zum Laden nutzen. In der „main.ts“ wird der „NiceService“ registriert:

.provide(NiceServiceKey, new NiceService())

Genutzt wird diese Instanz an beliebiger stelle mit:

const niceService = inject(NiceServiceKey);