我用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需要做什么?


这里的主要规则是:

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

所以,试着导出它:

@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为每个@ ngmodule创建了可传递的模块。

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

当angular编译属于模块X的模板时,它会使用在X. transitivmodule .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

按照上图这样做

YComponent can't use ZComponent in its template because directives array of Transitive module Y doesn't contain ZComponent because YModule has not imported ZModule whose transitive module contains ZComponent in exportedDirectives array. Within XComponent template we can use ZComponent because Transitive module X has directives array that contains ZComponent because XModule imports module (YModule) that exports module (ZModule) that exports directive ZComponent Within AppComponent template we can't use XComponent because AppModule imports XModule but XModule doesn't exports XComponent.

另请参阅

为什么惰性加载模块必须导入commonModule?角2 Angular模块常见问题 在NgModule中,声明、提供者和导入之间有什么区别?

你必须从你的NgModule中导出它:

@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的解释(非常感谢)。 当使用延迟加载时,在任何其他模块中重用一个在模块中声明的组件,这是一个缺失的部分。

第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:

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

@NgModule({
declarations: [
    FirstPage,
    ImportantComponent // <-- Enable using the component html tag in current module
],
imports: [
  IonicPageModule.forChild(NotImportantPage),
  TranslateModule.forChild(),
],
exports: [
    FirstPage,
    ImportantComponent // <--- Enable using the component in other modules
  ]
})
export class FirstPageModule { }

模块2:

通过导入FirstPageModule来重用ImportantComponent

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