API文档
# API 文档
# 简介
本库是在@kaokei/di的基础上增加了若干新的 API,@kaokei/di提供的 API 都是可用的。
# declareProviders
declareProviders([
SomeService,
{
provide: SomeService,
useClass: SomeService,
},
{
provide: SomeService,
useClass: SomeOtherService,
},
{
provide: SomeService,
useValue: someServiceInstance,
},
{
provide: SomeService,
useExisting: SomeOtherService,
},
{
provide: SomeService,
useFactory: (dependService1, dependService2, dependService3) => {
return someServiceInstance;
},
deps: [DependService1, DependService2, DependService3],
},
]);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
本函数只能在 setup 函数中使用。建议在 setup 的第一行使用,至少也需要在 useService 函数之前使用,否则效果可能不符合预期。
因为当前组件可能依赖了多个服务,所以可以一次性定义多个服务的 provider,所以本函数的参数是一个数组。以上列出了 provider 的所有可能形式,每种 provider 代表了不同的生成服务的方式。
本函数的作用是在当前组件中关联一个 Injector,这个 Injector 中根据providers
声明了token
与对应的服务的关联关系。这样后续在使用useService
的时候就能根据token
找到对应的服务。
我们知道整个应用的所有组件会组成一颗组件树,本函数的作用就是在这颗组件树中的某些组件关联 Injector。这些 Injector 也会形成一颗类似的树形结构,这棵树的根部是一个根Injector
。
当然正常情况下,Injector 的数量会比组件的数量少很多,因为并不是所有的组件都需要关联一个 Injector。
想象一下,如果整个应用中所有的服务都是不同的,都是全局单例的。那么我们可能不需要使用declareProviders
,只要把所有服务都放到根Injector
中即可。
但是如果我们想要实现服务实例的生命周期和某个组件保持一致,最常见的场景就是路由组件。那么显然我们应该把服务定义在对应的路由组件中,而不是在根 Injector 中。因为当路由组件销毁时,对应的 Inejctor 也会销毁,然后 Injector 中的服务的实例对象也会被销毁。反之如果所有服务都是放在全局的根 Injector 中,因为根组件是不会销毁的,所以根 Injector 也不会销毁,导致某些数据一直存在于根 Injector 中,但是这也许不是我们想要的。
除了控制服务实例的生命周期,另一个功能就是可以实现同一个服务的多例效果。显而易见如果我们在不同的组件中调用declareProviders
,并且配置了同一个服务。那么在获取服务实例时就能得到同一个服务的不同实例,因为在不同的组件中是对应的不同的 Injector,就算是相同的服务,也会生成不同的实例对象。
提示
declareProviders
只能在 setup 中使用,且在同一个 setup 中只能调用一次,且应该在最顶部调用。
# useService
// 示例1
const someService = useService(SomeService);
// 示例2
const [someService1, someService2, someService3] = useService([
SomeService1,
SomeService2,
SomeService3,
]);
// 示例3
const someService = useService(SomeService, {
skip: true,
optional: true,
});
// 示例4
const someService = useService(SomeService, {
self: true,
optional: true,
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
只能在 setup 函数中使用。
我们可以一次获取单个服务的实例对象,也可以一次性获取多个服务的实例对象。
第一个参数是 token 或者 token 数组。而且可以指定第二个参数 options 对象来控制 useService 的解析过程。
useService 的作用非常类似@Inject。尤其是第二个参数 options 对象,支持这些属性:
- self 对应装饰器@Self
- skip 对应装饰器@Skip
- optional 对应装饰器@Optional
其实 useService 的作用是等价于装饰器@Inject
的,只不过装饰器只能在类中使用,不能在函数上使用,所以只好额外提供一个 useService 函数在 setup 函数中使用。
比如在 angular 中,就不需要这样一个函数来获取实例。因为 angular 应用中组件和服务的形式只能是类,在组件类中可以直接使用@Inject 来注入服务或者其他组件。
但是在 Vue 中,Vue 组件的形式有两种,一种是类组件,这种情况我们也可以不使用 useService,可以直接使用@Inject 来注入服务;另一种情况则是 Option 组件,因为 Option 组件不是类,所以不能使用装饰器。只能使用 useService 这种类似 hooks 的方法类获取实例对象。
useService 非常优秀的一点就是返回值都是自带类型的,从而可以非常方便的使用.
来知道这个服务有哪些属性和方法。
另外一点就是其返回值已经是 reactive 的,可以直接在 vue 模版中使用。
提示
useService
只能在 setup 中使用,可以多次使用。
# declareRootProviders
语法和declareProviders
一致,只不过作用有所区别。
declareProviders 的作用是在调用的组件中关联一个 Injector,并声明一些 providres。但是declareRootProviders
的作用是直接在根 Injector 中声明 providers。
declareProviders 只能在 setup 函数中调用,且只能调用一次,但是 declareRootProviders 没有这些限制。
提示
注意到 declareRootProviders 声明的服务是全局的,那么后续通过useService
也是可以使用到这些服务的。
# useRootService
语法和useService
一致,只不过作用有所区别。
useService 会从当前组件关联的 Injector 开始寻找对应的 Provider,如果没有找到,那么会从父组件关联的 Injector 中寻找,直到根 Injector 为止。
useRootService 则是直接从根 Injector 中寻找对应的 Provider。
useService 只能在 setup 函数中调用,但是 useRootService 没有这个限制。