使用来自另一个模块的组件
Posted
技术标签:
【中文标题】使用来自另一个模块的组件【英文标题】:Use component from another module 【发布时间】:2017-01-28 19:58:26 【问题描述】:我有使用 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
?
【问题讨论】:
【参考方案1】:一个非常棒的方法是从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) 得到这个。
【讨论】:
NgModuleFactoryLoader 现在已被弃用,那么它最好的替代方法是什么?【参考方案2】:这里的主要规则是:
在组件模板编译期间适用的选择器由声明该组件的模块以及该模块导入的导出的传递闭包确定。
所以,尝试导出它:
@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
s 创建传递模块。
此模块收集从另一个模块导入的指令(如果导入模块的传递模块具有导出指令)或在当前模块中声明。
当 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
按照上图这样
YComponent
不能在其模板中使用ZComponent
,因为Transitive module Y
的directives
数组不包含ZComponent
,因为YModule
尚未导入ZModule
,其传递模块包含ZComponent
exportedDirectives
数组。
在XComponent
模板中,我们可以使用ZComponent
,因为Transitive module X
具有包含ZComponent
的指令数组,因为
XModule
导入模块 (YModule
) 导出模块 (ZModule
) 导出指令 ZComponent
在AppComponent
模板中我们不能使用XComponent
,因为AppModule
导入XModule
但XModule
不导出XComponent
。
另见
why lazy loaded module has to import commonModule? Angular 2
Angular Module FAQs
What is the difference between declarations, providers, and import in NgModule?
【讨论】:
如何在导入模块的路由定义中使用这个“TaskCardComponent”? 多么棒的答案。你创建了图纸吗?如果是这样,我无语了。不是每个人都在他们的答案中付出了这样的努力。谢谢 @Royi 是的,这是我的照片 :) 它基于来自github.com/angular/angular/blob/master/packages/compiler/src/…的源代码 @yuruzi,没有引用***.com/questions/47246638/…plnkr.co/edit/DnnjFBa3HLzFKNIdE4q5?p=preview,我无法直接传递dom节点 @yurzui ...我不明白 YComponent 如何导出 ZModule,因为我将其视为一个单独的文件(y.module.ts)并且它没有任何导入,因此导出其他模块(即 z.module.ts)[如果它的基本问题请告诉我]【参考方案3】:(角度 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
【讨论】:
虽然不像原来那样冗长,但这是您需要做的两件事,而导出组件是最常被遗忘的一件事。这是一个简单的答案。【参考方案4】:解决了如何在其他模块中使用模块中声明的组件。
基于 Royi Namir 的解释(非常感谢)。 在使用延迟加载时,缺少在任何其他模块中重用模块中声明的组件的部分。
1st:导出包含它的模块中的组件:
@NgModule(
declarations: [TaskCardComponent],
imports: [MdCardModule],
exports: [TaskCardComponent] <== this line
)
export class TaskModule
2nd:在要使用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
像这样,第二个模块导入第一个模块,该模块导入和导出组件。
当我们在第二个模块中导入模块时,我们需要再次导出它。现在我们可以在第二个模块中使用第一个组件了。
【讨论】:
【参考方案5】:请注意,为了创建所谓的“功能模块”,您需要在其中导入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
【讨论】:
【参考方案6】:无论您想从另一个模块中使用什么,只需将其放入 导出数组。 像这样-
@NgModule(
declarations: [TaskCardComponent],
exports: [TaskCardComponent],
imports: [MdCardModule]
)
【讨论】:
【参考方案7】:你必须从你的NgModule
export
它:
@NgModule(
declarations: [TaskCardComponent],
exports: [TaskCardComponent],
imports: [MdCardModule],
providers: []
)
export class TaskModule
【讨论】:
这个工作,直到 TaskModule 被导入 AppModule。当 TaskModule 被延迟加载时它会失败。以上是关于使用来自另一个模块的组件的主要内容,如果未能解决你的问题,请参考以下文章