我有使用 angular-cli 生成的 Angular 2.0.0 应用程序。
当我创建一个组件并将其添加到 AppModule
的声明数组时,一切都很好,它可以工作。
我决定将组件分开,因此我创建了一个 TaskModule
和一个组件 TaskCard
。现在我想在 AppModule
的一个组件(Board
组件)中使用 TaskCard
。
应用模块:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { BoardComponent } from './board/board.component';
import { LoginComponent } from './login/login.component';
import { MdButtonModule } from '@angular2-material/button';
import { MdInputModule } from '@angular2-material/input';
import { MdToolbarModule } from '@angular2-material/toolbar';
import { routing, appRoutingProviders} from './app.routing';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { UserService } from './services/user/user.service';
import { TaskModule } from './task/task.module';
@NgModule({
declarations: [
AppComponent,
BoardComponent,// I want to use TaskCard in this component
LoginComponent,
PageNotFoundComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
MdButtonModule,
MdInputModule,
MdToolbarModule,
routing,
TaskModule // TaskCard is in this module
],
providers: [UserService],
bootstrap: [AppComponent]
})
export class AppModule { }
任务模块:
import { NgModule } from '@angular/core';
import { TaskCardComponent } from './task-card/task-card.component';
import { MdCardModule } from '@angular2-material/card';
@NgModule({
declarations: [TaskCardComponent],
imports: [MdCardModule],
providers: []
})
export class TaskModule{}
整个项目在 https://github.com/evgdim/angular2(看板板文件夹)上可用
我错过了什么?我需要做什么才能在 BoardComponent
中使用 TaskCardComponent
?
这里的主要规则是:
在组件模板编译期间适用的选择器由声明该组件的模块以及该模块导入的导出的传递闭包确定。
所以,尝试导出它:
@NgModule({
declarations: [TaskCardComponent],
imports: [MdCardModule],
exports: [TaskCardComponent] // <== export the component you want to use in another module
})
export class TaskModule{}
我应该出口什么?
导出其他模块中的组件应该能够在其模板中引用的可声明类。这些是你的公开课。如果您不导出一个类,它会保持私有,仅对该模块中声明的其他组件可见。
在你创建一个新模块的那一刻,不管你是否懒惰,任何新模块并在其中声明任何内容,新模块都会有一个干净的状态(正如 Ward Bell 在 { 1})
Angular 为每个 @NgModule
创建传递模块。
该模块收集从另一个模块导入的指令(如果导入模块的传递模块具有导出指令)或在当前模块中声明。
当 Angular 编译属于模块 X
的模板时,它会使用那些在 X.transitiveModule.directives 中收集的指令。
compiledTemplate = new CompiledTemplate(
false, compMeta.type, compMeta, ngModule, ngModule.transitiveModule.directives);
https://github.com/angular/angular/blob/4.2.x/packages/compiler/src/jit/compiler.ts#L250-L251
https://i.stack.imgur.com/oQGSN.png
按照上图这样
YComponent 不能在其模板中使用 ZComponent,因为 Transitive 模块 Y 的指令数组不包含 ZComponent,因为 YModule 尚未导入 ZModule,其可传递模块在 exportDirectives 数组中包含 ZComponent。
在 XComponent 模板中,我们可以使用 ZComponent,因为传递模块 X 具有包含 ZComponent 的指令数组,因为 XModule 导入模块 (YModule),导出模块 (ZModule),导出指令 ZComponent
在 AppComponent 模板中,我们不能使用 XComponent,因为 AppModule 导入 XModule 但 XModule 不导出 XComponent。
也可以看看
为什么延迟加载的模块必须导入 commonModule?角 2
Angular 模块常见问题解答
NgModule 中的声明、提供者和导入有什么区别?
(角度 2 - 角度 7)
组件只能在单个模块中声明。为了使用来自另一个模块的组件,您需要做两个简单的任务:
导出其他模块中的组件 导入其他模块,到当前模块中
第一个模块:
有一个组件(让我们称之为:“ImportantCopmonent”),我们想在第二个模块的页面中重新使用。
@NgModule({
declarations: [
FirstPage,
ImportantCopmonent // <-- Enable using the component html tag in current module
],
imports: [
IonicPageModule.forChild(NotImportantPage),
TranslateModule.forChild(),
],
exports: [
FirstPage,
ImportantCopmonent // <--- Enable using the component in other modules
]
})
export class FirstPageModule { }
第二模块:
通过导入 FirstPageModule 重用“ImportantCopmonent”
@NgModule({
declarations: [
SecondPage,
Example2ndComponent,
Example3rdComponent
],
imports: [
IonicPageModule.forChild(SecondPage),
TranslateModule.forChild(),
FirstPageModule // <--- this Imports the source module, with its exports
],
exports: [
SecondPage,
]
})
export class SecondPageModule { }
您必须从您的 NgModule
中export
它:
@NgModule({
declarations: [TaskCardComponent],
exports: [TaskCardComponent],
imports: [MdCardModule],
providers: []
})
export class TaskModule{}
请注意,为了创建所谓的“功能模块”,您需要在其中导入 CommonModule
。因此,您的模块初始化代码将如下所示:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TaskCardComponent } from './task-card/task-card.component';
import { MdCardModule } from '@angular2-material/card';
@NgModule({
imports: [
CommonModule,
MdCardModule
],
declarations: [
TaskCardComponent
],
exports: [
TaskCardComponent
]
})
export class TaskModule { }
此处提供更多信息:https://angular.io/guide/ngmodule#create-the-feature-module
无论您想从另一个模块中使用什么,只需将其放入导出数组中即可。像这样-
@NgModule({
declarations: [TaskCardComponent],
exports: [TaskCardComponent],
imports: [MdCardModule]
})
一个大而好的方法是从 NgModuleFactory
加载模块,您可以通过调用以下命令将模块加载到另一个模块中:
constructor(private loader: NgModuleFactoryLoader, private injector: Injector) {}
loadModule(path: string) {
this.loader.load(path).then((moduleFactory: NgModuleFactory<any>) => {
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.injector);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
this.lazyOutlet.createComponent(compFactory);
});
}
我是从 here (archived) 那里得到的。
解决了如何在其他模块中使用模块中声明的组件。
基于 Royi Namir 的解释(非常感谢)。在使用延迟加载时,缺少在任何其他模块中重用模块中声明的组件的部分。
1st:导出包含它的模块中的组件:
@NgModule({
declarations: [TaskCardComponent],
imports: [MdCardModule],
exports: [TaskCardComponent] <== this line
})
export class TaskModule{}
第二:在要使用TaskCardComponent的模块中:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MdCardModule } from '@angular2-material/card';
@NgModule({
imports: [
CommonModule,
MdCardModule
],
providers: [],
exports:[ MdCardModule ] <== this line
})
export class TaskModule{}
像这样,第二个模块导入导入和导出组件的第一个模块。
当我们在第二个模块中导入模块时,我们需要再次导出它。现在我们可以在第二个模块中使用第一个组件。