根据官方文档,似乎只要我们停留在基于对象的结构上,我们就可以使用依赖注入功能。
这是我的问题。我正在使用TypeScript来实现这个目标(基于类)。我将Inversify
用作 IoC 容器。我最初的想法是这样的:
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 {
}
当我检查浏览器的开发控制台时,我能够看到container
已设置为_provided
字段。这是Hello.ts
,App.ts
的子组件:
Hello.ts
:
@Component({
name: "Hello",
inject: [ "container" ]
})
export default class Hello extends Vue {
created (): void {
console.log(this);
}
}
由于App.ts
可以通过vue-router
访问Hello.ts
,因此它没有将Hello.ts
注册为子组件。我期待注入的容器应该出现在_injected
或类似的东西上。但是,我找不到它。我将inject
属性值从"container"
更改为{ "container": Symbol("Container") }
,但仍然找不到它。
服务定位器:
使用服务定位器而不是provide/inject
对工作正常:
// 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);
}
}
但是,我想避免在此处使用服务定位器模式。我在使用provide/inject
对进行依赖注入时是否遗漏了什么?
我找到了解决方案。如果我们使用vue-class-component
和vue-property-decorator
,我们可以实现这一目标——使用provide
/inject
对。这是我的代码片段:
// 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>
在最顶层的 Vue 组件App.vue
中,我们提供了container
实例,以便它的所有子组件都可以使用它。这是它的子组件之一,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>
子组件使用@Inject(Symbol)
修饰器从App.vue
解析注入container
实例。
我用英语和韩语写了一篇关于这个的博客文章。
呵呵