上节模块导入的时候,我们留下了一些问题,今天我们来处理一部分,完成模块的重新导出功能
前置知识
模块可以重新导出他们导入的模块,从而使其可用于导入该模块的其他模块。也就是说exports不仅能导出providers,也可以导出模块
比如有模块A, B, C,模块B导入了A并将A重新导出,模块C导入了B,那么模块C可以通过使用A和B中导出的providers
1 2 3 4 5 6 7 8 9 10 11 12 13
| let moduleA = { providers: [1, 2, 3], exports: [1, 2] } let moduleB = { imports: [moduleA], providers: [4, 5], exports: [moduleA, 4] } let moduleC = { imports: [moduleB] }
|
源码实现
由于我们会导出模块,所以我们就需要一个方法来判断是不是模块,为了实现这个,我们对@Module装饰器进行一下调整,添加一个新的元数据做标识
1 2 3 4 5 6 7 8 9 10 11 12 13
| import 'reflect-metadata'
export function Module(metadata: ModuleMetadata): ClassDecorator { return (target: Function) => { ~ Reflect.defineMetadata('isModule', true, target) } }
|
然后在nest-application中做相应的解析,我们调整了initProviders方法并添加了两个新的方法:
1 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 27 28 29 30 31 32 33 34 35 36 37 38 39
|
initProviders() { const imports = Reflect.getMetadata('imports', this.module) ?? [] for (const importModule of imports) { this.registerProvidersFromModule(importModule) } const providers = Reflect.getMetadata('providers', this.module) ?? [] for (const provider of providers) { this.addProvider(provider) } }
isModule(token) { return token && token instanceof Function && !!Reflect.getMetadata('isModule', token) } private registerProvidersFromModule(module) { const importedProviders = Reflect.getMetadata('providers', module) ?? [] const exports = Reflect.getMetadata('exports', module) ?? [] for (const exportToken of exports) { if (this.isModule(exportToken)) { this.registerProvidersFromModule(exportToken) } else { const provider = importedProviders.find(pro => pro === exportToken || pro.provide === exportToken) if (provider) { this.addProvider(provider) } }
} }
|
前面的五个问题,我们已经基本实现了1,2,5三个