beroendeinjektion - Hur man löser injicerade instanser i Vue.js med TypeScript
Enligt det officiella dokumentet verkar det som att vi kan använda funktionaliteten för beroendeinjektion så länge vi håller oss till objektbaserad struktur.
Här är min fråga. Jag använder TypeScript för att uppnå detta mål (klassbaserat). Jag kommer att använda Inversify som en IoC-container. Min initiala idé var något i stil med:
DependencyConfig.ts:
import { Container } from "inversify";
import "reflect-metadata";
import Warrior from "./interfaces/Warrior";
import { Ninja } from "./models/Warrior";
let container = new Container();
container.bind<Warrior>(Symbol("Warrior")).to(Ninja);
export default container;
App.ts:
import container from "./DependencyConfig";
@Component({
name: "App",
provide: container
})
export default class App extends Vue {
}
När jag kontrollerade i min webbläsares utvecklarkonsol kunde jag se att container har satts till fältet _provided. Här är Hello.ts, barnkomponenten till App.ts:
Hello.ts:
@Component({
name: "Hello",
inject: [ "container" ]
})
export default class Hello extends Vue {
created (): void {
console.log(this);
}
}
Eftersom App.ts kunde få åtkomst till Hello.ts genom vue-router, registrerade det inte Hello.ts som en barnkomponent. Jag förväntade mig att den injicerade containern skulle dyka upp på _injected eller något liknande. Jag kunde dock inte hitta den. Jag ändrade värdet för inject-egenskapen från "container" till { "container": Symbol("Container") }, men jag kunde fortfarande inte hitta den.
Tjänste Locator:
Det fungerar bra att använda en servicelokalisator istället för provide/inject-paret:
// App.ts
@Component({
name: "App"
})
export default class App extends Vue {
}
// Hello.ts
import container from "./DependencyConfig";
@Component({
name: "Hello"
})
export default class Hello extends Vue {
created (): void {
var ninja = container.get<Ninja>(Symbol("Warrior"));
console.log(ninja.name);
}
}
Jag vill dock undvika att använda service locator-mönstret här. Missade jag något när jag använde provide/inject-paret för beroendeinjektion?
Svar #1
Jag hittade en lösning. Om vi använder vue-class-component och vue-property-decorator kan vi uppnå detta mål - genom att använda provide/inject-paret. Här är mitt kodexempel:
// App.vue
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import SERVICE_IDENTIFIER from "./models/Identifiers";
import container from "./configs/DependencyConfigs";
@Component({
name: "App",
// Provides IoC container at the top level of VueComponent
provide: {
[SERVICE_IDENTIFIER.CONTAINER]: container
}
})
export default class App extends Vue {
}
</script>
På den översta Vue-komponenten, App.vue, tillhandahåller vi container-instansen så att alla dess underordnade komponenter kan använda den. Här är en av dess underordnade komponenter, Ninja.vue:
// Ninja.vue
<script lang="ts">
import Vue from "vue";
// Imports both Component and Inject decorators from vue-property-decorator,
// instead of vue-class-component
import { Component, Inject } from "vue-property-decorator";
import { Container } from "inversify";
import SERVICE_IDENTIFIER from "../models/Identifiers";
import { Ninja as _Ninja } from "../models/Warrior";
@Component({
name: "Ninja"
})
export default class Ninja extends Vue {
public warrior: string;
public weapon: string;
// IoC container provided from App.ts is injected here
@Inject(SERVICE_IDENTIFIER.CONTAINER)
private _container: Container;
private _ninja: _Ninja;
created (): void {
this._ninja = this._container.get<_Ninja>(SERVICE_IDENTIFIER.WARRIOR);
this.warrior = this._ninja.name;
this.weapon = this._ninja.weapon.name;
}
}
</script>
Barnkomponenten använder @Inject(Symbol) dekoratorn för att lösa den injicerade container instansen från App.vue.
Jag skrev ett blogginlägg om detta både på engelska och koreanska.
Hoppas detta hjälper
