使用来自其他模块的组件

我用Angular -cli生成了Angular 2.0.0应用。

当我创建一个组件并将其添加到AppModule的declarations数组时,一切都很好,它工作了。

我决定分离组件,所以我创建了TaskModule和组件TaskCard。现在我想在AppModule的一个组件(Board组件)中使用TaskCard

AppModule:

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 { }

TaskModule:

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 ?

317607 次浏览

这里的主要规则是:

在编译组件模板期间适用的选择器由声明该组件的模块和该模块导入的导出的传递闭包决定。

所以,试着导出它:

@NgModule({
declarations: [TaskCardComponent],
imports: [MdCardModule],
exports: [TaskCardComponent] // <== export the component you want to use in another module
})
export class TaskModule{}

我应该导出什么?

导出其他模块中的组件应该是的可声明类 能够在他们的模板中引用。这些是你的公共类。 如果不导出类,它将保持私有,仅对其他类可见

当你创建一个新模块时,不管是不是懒的,任何一个新模块,你在它里面声明了任何东西,这个新模块的状态是干净的(如Ward Bell在https://devchat.tv/adv-in-angular/119-aia-avoiding-common-pitfalls-in-angular2中所说)

Angular为每个__abc0创建传递模块

此模块收集从其他模块导入的指令(如果导入模块的可传递模块有导出指令)或在当前模块中声明的指令

当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

enter image description here

按照上图这样做

  • YComponent不能在模板中使用ZComponent,因为Transitive module Ydirectives数组不包含ZComponent,因为YModule没有导入ZModule,其传递模块包含exportedDirectives数组中的ZComponent

  • XComponent模板中,我们可以使用ZComponent,因为Transitive module X有包含ZComponent的指令数组,因为 XModule导入模块(YModule),该模块导出模块(ZModule),导出指令ZComponent

  • AppComponent模板中,我们不能使用XComponent,因为AppModule导入XModule,但XModule不导出XComponent

另请参阅

你必须从你的NgModuleexport它:

@NgModule({
declarations: [TaskCardComponent],
exports: [TaskCardComponent],
imports: [MdCardModule],
providers: []
})
export class TaskModule{}
不管你想从另一个模块中使用什么,只要把它放在输出数组中。 像这样-

 @NgModule({
declarations: [TaskCardComponent],
exports: [TaskCardComponent],
imports: [MdCardModule]
})

注意,为了创建所谓的“特性模块”,你需要在其中导入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

解决了如何在另一个模块中使用一个模块中声明的组件。

基于Royi Namir的解释(非常感谢)。 当使用延迟加载时,在任何其他模块中重用一个在模块中声明的组件,这是一个缺失的部分。< / p >

第1步:导出包含它的模块中的组件:

@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{}

第二个模块导入第一个模块,第一个模块导入并导出组件。

当我们导入第二个模块中的模块时,我们需要再次导出它。现在我们可以在第二个模块中使用第一个组件。

一个伟大的方法是从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);
});
}

我从在这里 (归档)得到这个。

(Angular 2 - Angular 7)

组件只能在单个模块中声明。 为了使用来自另一个模块的组件,您需要完成两个简单的任务:

  1. 导出另一个模块中的组件
  2. 导入另一个模块到当前模块中

模块1:

有一个组件(让我们叫它:“ImportantCopmonent”),我们想在第2模块的页面中重用。

@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 { }

模块2:

通过导入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 { }