ใช้ส่วนประกอบจากโมดูลอื่น


199

ฉันมีแอป Angular 2.0.0 ที่สร้างขึ้นด้วย angular-cli

เมื่อฉันสร้างองค์ประกอบและเพิ่มเข้าไปในAppModuleอาร์เรย์การประกาศของมันเป็นสิ่งที่ดีมันทำงานได้ดี

ฉันตัดสินใจที่จะแยกชิ้นส่วนเพื่อให้ฉันสร้างและส่วนประกอบTaskModule TaskCardตอนนี้ฉันต้องการใช้TaskCardหนึ่งในองค์ประกอบของAppModule( Boardส่วนประกอบ)

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 (โฟลเดอร์ kanban-board)

ฉันพลาดอะไรไป ฉันจะทำอะไรต้องทำเพื่อการใช้งานTaskCardComponentในBoardComponent?

คำตอบ:


389

กฎหลักที่นี่คือ:

ตัวเลือกที่ใช้งานได้ในระหว่างการรวบรวมเท็มเพลตส่วนประกอบถูกกำหนดโดยโมดูลที่ประกาศส่วนประกอบนั้นและการปิดการส่งผ่านของการส่งออกของการนำเข้าของโมดูลนั้น

ดังนั้นพยายามส่งออก:

@NgModule({
  declarations: [TaskCardComponent],
  imports: [MdCardModule],
  exports: [TaskCardComponent] <== this line
})
export class TaskModule{}

ฉันควรส่งออกอะไร

ส่งออกคลาสที่ประกาศได้ซึ่งส่วนประกอบในโมดูลอื่นควรสามารถอ้างอิงได้ในเทมเพลต นี่คือชั้นเรียนสาธารณะของคุณ หากคุณไม่ส่งออกชั้นเรียนจะคงความเป็นส่วนตัวโดยจะมองเห็นได้เฉพาะส่วนประกอบอื่น ๆ ที่ประกาศในโมดูลนี้

นาทีที่คุณสร้างโมดูลใหม่ขี้เกียจหรือไม่โมดูลใหม่ใด ๆ และคุณประกาศอะไรเข้าไปในนั้นโมดูลใหม่นั้นมีสถานะที่สะอาด (ดังที่ Ward Bell กล่าวใน https://devchat.tv/adv-in-angular/119 -aia-Avoid-common-pitfalls-in-angular2 )

Angular สร้างโมดูล transitiveสำหรับแต่ละ@NgModules

โมดูลนี้จะเก็บรวบรวมคำสั่งที่นำเข้าทั้งจากโมดูลอื่น (ถ้าโมดูลสกรรมกริยาของโมดูลที่นำเข้ามีการส่งออกสั่ง) หรือประกาศในโมดูลปัจจุบัน

เมื่อคอมไพล์เชิงมุมแม่แบบที่เป็นโมดูล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ในแม่แบบของมันได้เนื่องจากdirectivesอาร์เรย์ของTransitive module Yไม่มีZComponentเนื่องจากYModuleไม่ได้นำเข้าZModuleซึ่งมีโมดูล transitive ZComponentในexportedDirectivesอาร์เรย์

  • ภายในXComponentเทมเพลตเราสามารถใช้ZComponentเพราะTransitive module Xมีอาเรย์คำสั่งที่มีZComponentเพราะอิม XModuleปอร์ตโมดูล ( YModule) ที่เอ็กซ์พอร์ตโมดูล ( ZModule) ที่ส่งออกคำสั่งZComponent

  • ภายในAppComponentแม่แบบเราไม่สามารถใช้XComponentเพราะAppModuleการนำเข้าXModuleแต่ไม่ได้ส่งออกXModuleXComponent

ดูสิ่งนี้ด้วย


13
ฉันจะใช้ "TaskCardComponent" นี้ในการกำหนดเส้นทางในโมดูลการนำเข้าได้อย่างไร
jackOfAll

17
ช่างเป็นคำตอบที่ยอดเยี่ยม คุณสร้างภาพวาดหรือไม่ ถ้าเป็นเช่นนั้นฉันพูดไม่ออก ไม่ใช่ทุกคนที่ใช้ความพยายามดังกล่าวในคำตอบของพวกเขา ขอบคุณ
Royi Namir

4
@Royi ใช่นี่คือรูปของฉัน :) มันขึ้นอยู่กับซอร์สโค้ดจากgithub.com/angular/angular/blob/master/packages/compiler/src/…
yurzui

@ yuruzi ฉันไม่สามารถส่งโหนด dom โดยตรงโดยไม่มีการอ้างอิงstackoverflow.com/questions/47246638/… plnkr.co/edit/DnnjFBa3HLzFKNIdE4q5?p=preview
Karty

@ yurzui ... ฉันไม่เข้าใจว่า YComponent ส่งออก ZModule ได้อย่างไรเนื่องจากฉันเห็นว่าเป็นไฟล์แยกต่างหาก (y.module.ts) และไม่มีการนำเข้าใด ๆ เพื่อส่งออกโมดูลอื่น (ซึ่งเป็น z .module.ts) [ให้ฉันถ้าคำถามพื้นฐานของมัน]
OmGanesh

42

คุณต้องไปexportจากNgModule:

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

2
ใช้งานได้จนถึง TaskModule จะถูกนำเข้าใน AppModule มันล้มเหลวเมื่อ TaskModule ถูก lazyloaded
อรุณ

40

(เชิงมุม 2 - เชิงมุม 7)

สามารถประกาศคอมโพเนนต์ได้ในโมดูลเดียวเท่านั้น ในการใช้ส่วนประกอบจากโมดูลอื่นคุณต้องดำเนินการอย่างง่ายสองอย่าง:

  1. ส่งออกส่วนประกอบในโมดูลอื่น
  2. นำเข้าโมดูลอื่นเข้าสู่โมดูลปัจจุบัน

โมดูลที่ 1:

มีองค์ประกอบ (เรียกว่า: "สิ่งสำคัญโคโมน") เราต้องการนำกลับมาใช้ในหน้าโมดูลที่ 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 { }

โมดูลที่สอง:

ใช้ "ImportantCopmonent" ซ้ำโดยนำเข้า FirstPageModule

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

2

โปรดทราบว่าในการสร้าง "feature module" คุณจะต้องนำเข้า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


0

สิ่งที่คุณต้องการใช้จากโมดูลอื่นเพียงแค่ใส่มันในอาร์เรย์การส่งออก แบบนี้-

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

0

วิธีการที่ยอดเยี่ยมวิธีหนึ่งที่ยอดเยี่ยมคือการโหลดโมดูลจาก a 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);
    });
}

ผมได้รับนี้จากที่นี่


NgModuleFactoryLoader เลิกใช้แล้วดังนั้นวิธีที่ดีที่สุดในการทำสิ่งนี้คืออะไร?
Muzaffar Mahmood

-2

ได้รับการแก้ไขวิธีใช้ส่วนประกอบที่ประกาศในโมดูลในโมดูลอื่น

ตามคำอธิบายของ Royi Namir (ขอบคุณมาก) มีชิ้นส่วนที่ขาดหายไปเพื่อนำส่วนประกอบที่ประกาศในโมดูลไปใช้ในโมดูลอื่น ๆ ในขณะที่ใช้งานการโหลดแบบสันหลังยาว

วันที่ 1: ส่งออกส่วนประกอบในโมดูลซึ่งมี:

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

เช่นนี้โมดูลที่สองนำเข้าโมดูลแรกซึ่งนำเข้าและส่งออกส่วนประกอบ

เมื่อเรานำเข้าโมดูลในโมดูลที่สองเราจำเป็นต้องส่งออกอีกครั้ง ตอนนี้เราสามารถใช้องค์ประกอบแรกในโมดูลที่สอง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.