框架开发人员喜欢通过实现依赖项注入概念来吹嘘。下面的实现是本机的、简单的和类型安全的.
// All below gateways and services are the abstractions
type ApplicationDependencies = Readonly<{
gateways: Readonly<{
category: CategoryGateway;
product: ProductGateway;
}>;
services: Readonly<{
authentication: AuthenticationService;
}>;
}>;
export default abstract class DependenciesInjector {
private static dependencies: ApplicationDependencies | null = null;
public static setDependencies(dependencies: ApplicationDependencies): void {
DependenciesInjector.dependencies = dependencies;
}
private static getDependencies(): ApplicationDependencies {
if (DependenciesInjector.dependencies === null) {
throw new Error("The DependenciesInjector has not been initialized");
}
return DependenciesInjector.dependencies;
}
public static get gateways(): ApplicationDependencies["gateways"] {
return DependenciesInjector.getDependencies().gateways;
}
public static get services(): ApplicationDependencies["services"] {
return DependenciesInjector.getDependencies().services;
}
}
初始化必须在入口点执行:
ApplicationDependencies.setDependencies({
gateways: {
category: new CategoryAxiosGateway(),
product: new ProductAxiosGateway()
},
services: {
authentication: new AuthenticationCognitoService()
}
});
现在,可以将这些依赖项注入为
import { Vue as VueComponent, Options as VueComponentConfiguration } from "vue-property-decorator";
@VueComponentConfiguration({})
export default class CategoriesManager extends VueComponent {
private readonly categoryGateway!: CategoryGateway;
// It's O'K from the viewpoint of TypeScript, but this way `categoryGateway` will become to
// reactive field (Vue's 'data') which could be undesirably
// private readonly categoryGateway!: CategoryGateway = DependenciesInjector.gateways.category;
public created(): void {
this.categoryGateway = DependenciesInjector.gateways.category;
}
}
以上方法对于大多数控制台和服务器应用程序来说已经足够好了,但是对于前端应用程序来说则不是最优的。它可能是数十个依赖项,一旦访问应用程序的任何页面,它们都将立即初始化。
如何解决这个问题?概念上的答案是“模块动态加载的操作”AKA“延迟加载”。我想问的是,在不改变注入方法的情况下(如上述Vue组件所示),它能否实现?如果是--如何实现?
现有实现的示例
Vue-路由器
Vue路由器支持开箱即入的动态导入,这意味着您可以用动态导入替换静态导入:
导入(‘/视图/UserDetails.vue’) const路由器= createRouter({ // .路由:{ path:‘/user/:id’,组件: UserDetails },})‘’
因此,对组件的访问不会改变。
NestJS
为了按需加载模块,
提供了可以以正常方式注入到类中的LazyModuleLoader类:
构造函数(私有lazyModuleLoader: LazyModuleLoader) {}
思考我的案子的方式
我们不能像以前那样设置依赖项。就像
ApplicationDependencies.setDependencies({
gateways: {
category: async (): Promise<CategoryGateway> => import("@Data/Gateways/CategoryAxiosGateway"),
product: async (): Promise<ProductGateway> => import("@Data/Gateways/ProductAxiosGateway")
},
services: {
authentication: async (): Promise<AuthenticationService> => import ("@Services/Gateways/ProductAxiosGateway")
}
});
只是草案而已。我们需要处理正确的类型、默认/非默认导入等等。我们还需要重写DependenciesInjector和ApplicationDependencies。但是如何访问这些依赖项呢?
@VueComponentConfiguration({})
export default class CategoriesManager extends VueComponent {
private readonly categoryGateway!: CategoryGateway;
public async created(): void {
this.categoryGateway = await DependenciesInjector.gateways.category;
}
}
我需要使crated
方法异步。我能否实现延迟加载,如保留上面的Vue组件,就像在前面的示例中一样?如果没有,哪一种最好的实现是可能的?
请注意,对这个主题的答案需要对概念的解释,而不是第三个-部分解决方案的建议。
发布于 2022-11-13 01:43:41
我也遇到了同样的问题,所以我为此编写了DI lib。就像一种魅力。对我和我的团队来说很有成效。
它被称为iti
,它有一些很好的响应绑定,所以应该可以将它们移植到Vue。
基本上,它是这样工作的:
您还可以检查文档上的React示例:
https://itijs.org/docs/with-react/react-full#async-request-for-single-item-in-iti
import { createContainer } from "iti"
// blue.ts
// export class Blue implements IColor {}
// rainbow-service.ts
// export class RainbowSegment { constructor(c: IColor) {} }
// async imports, no trace in runtime
export const container = createContainer()
.add(() => ({
blue: async () => {
const { Blue } = await import("./blue")
return new Blue()
},
}))
.add((ctx) => ({
blueRainbowSegment: async () => {
const { RainbowSegment } = await import("./rainbow-service")
return new RainbowSegment(ctx.blue)
},
}))
const blueSegment = await container.items.blueRainbowSegment
https://stackoverflow.com/questions/74169292
复制