【问题标题】:Use component from another module使用来自另一个模块的组件
【发布时间】:2017-01-28 19:58:26
【问题描述】:

我有使用 angular-cli 生成的 Angular 2.0.0 应用程序。

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

我决定将组件分开,所以我创建了一个TaskModule 和一个组件TaskCard。现在我想在AppModuleBoard 组件)的组件之一中使用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

【问题讨论】:

    标签: angular typescript angular-module


    【解决方案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 为每个@NgModules 创建传递模块

    此模块收集从另一个模块导入的指令(如果导入模块的传递模块具有导出指令)或在当前模块中声明

    当 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 Ydirectives 数组不包含ZComponent,因为YModule 尚未导入ZModule,其传递模块包含ZComponent exportedDirectives 数组。

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

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

    另见

    【讨论】:

    【解决方案3】:

    (角度 2 - 角度 7)

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

    1. 导出其他模块中的组件
    2. 将其他模块导入到当前模块中

    第一个模块:

    有一个组件(我们称之为“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】:

          你必须从你的NgModuleexport它:

          @NgModule({
            declarations: [TaskCardComponent],
            exports: [TaskCardComponent],
            imports: [MdCardModule],
            providers: []
          })
          export class TaskModule{}
          

          【讨论】:

          • 这个工作,直到 TaskModule 被导入 AppModule。当 TaskModule 被延迟加载时它会失败。
          猜你喜欢
          • 2017-04-22
          • 1970-01-01
          • 2020-04-16
          • 2019-05-13
          • 1970-01-01
          • 2021-12-01
          • 2019-07-23
          • 2021-03-14
          • 1970-01-01
          相关资源
          最近更新 更多