例如下面的代码没有按预期工作。假设我有按钮命名空间:
namespace Button {
@Component({
selector: 'super-button',
templateUrl: './button.component.html',
styleUrls: ['./button.component.scss']
})
export class ButtonComponent {}
@NgModule({
declarations: [
ButtonComponent
],
imports: [
CommonModule
],
exports: [ButtonComponent]
})
export class ButtonModule { }
}
export default Button;
在 app.module 中:
import Button from './button';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
Button.ButtonModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
我收到此编译错误:
<e> [webpack-dev-middleware] Error: [object Object]
<e> at analyzingFileEmitter (E:\Projects\Angular\test-app\node_modules\@ngtools\webpack\src\ivy\plugin.js:452:23)
<e> at processTicksAndRejections (node:internal/process/task_queues:96:5)
<e> at async AngularWebpackPlugin.rebuildRequiredFiles (E:\Projects\Angular\test-app\node_modules\@ngtools\webpack\src\ivy\plugin.js:277:36)
<e> at async E:\Projects\Angular\test-app\node_modules\@ngtools\webpack\src\ivy\plugin.js:218:17
更重要的是,如何将组件和模块拆分为不同的文件,同时仍将它们放在同一个命名空间中?我尝试了以下方法,但无济于事:https://www.typescriptlang.org/docs/handbook/namespaces.html#multi-file-namespaces
我的观点是用大量的组件和模块来组织项目。我有很多名称很长的文件来描述其功能,例如:
-> very-descriptive-A-list.module
-> very-descriptive-A-list.component
-> very-descriptive-A-list-item.component
-> very-descriptive-A-list-modal.component etc
我只想创建一个包含每个功能的命名空间,就像这样:
-> very-describtive-A namespace:
->> list.module,
->> list.component,
->> item.component
->> modal.component etc
-> very-describtive-B namespace:
->> list.module,
->> list.component,
->> item.component
->> modal.component etc
对于其他所有功能,依此类推。我只是在考虑减少文件名中的样板文件,这对 IDE 智能感知也有好处,因为命名空间内的组件被封装和隐藏。
回答1
Typescript 命名空间在这一点上基本上已经过时了。 TypeScript 在 ES 模块被添加到 ES6 之前就有这个概念。 TypeScript 的设计目标是尽可能使语言与 ECMA 保持同步,因此虽然它可能在 ECMA 之前有一个特性,但如果以后添加它,它将有利于本机实现。 TypeScript 的“外部模块”现在在很大程度上与 ES 模块没有区别,并且对于这两个用例来说都足够了。请参阅 https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html#needless-namespacing
您正在寻找的行为是 index.ts
文件的目的。通常,当给定目录有一个 index.ts
时,这意味着该目录的其他内容是“内部的”(即不被目录之外的任何东西使用),而从索引导出的东西是“外部模块” .
button
├── button-component.ts
├── button-module.ts
└── index.ts
index.ts
通常看起来像:
export { ButtonComponent } from './button-component';
export { ButtonModule } from './button-module';
对于您问题中的行为,您可以将整个模块导入到一个变量中,例如:
import * as Button from './button';
// ...
imports: [
Button.ButtonModule,
但是,更常见的是只导入所需的特定成员,例如:
import { ButtonModule } from './button';
你当然可以用任何一种方式来做,但前者更符合习惯,正如在同一个地方使用的 CommonModule
或 AppRoutingModule
所证明的那样。显式命名空间是不必要的,因为 import
的源代码没有歧义。
import * as
语法在一些导出大量你一起使用的东西的情况下很方便,但典型的用例是导出一组密切相关的函数的模块,而不是一堆类型。例如。
api/
├── create-user.ts
├── delete-user.ts
├── get-user.ts
├── index.ts
└── update-user.ts
import * as api from './api';
// ...
await api.getUser(123);
await api.deleteUser(123);
它与导出具有所有这些方法的对象的 api.ts
没有区别,但在单独的文件中组织代码很方便。