entryComponents ใน angular ngModule คืออะไร?


132

ฉันกำลังทำงานในIonicแอป ( 2.0.0-rc0) angular 2ซึ่งขึ้นอยู่กับ ดังนั้นการแนะนำใหม่ngModulesจึงรวมอยู่ด้วย ฉันกำลังเพิ่มapp.module.ts.ด้านล่างของฉัน

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { Users } from '../pages/users/users';

@NgModule({
  declarations: [
    MyApp,
    Users
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    Users
  ]
})
export class AppModule {}

มาentryComponentsทำอะไรที่นี่? Componentsถูกกำหนดไว้แล้วในdeclarations. แล้วอะไรคือความจำเป็นในการทำซ้ำ? จะเกิดอะไรขึ้นถ้าฉันไม่รวมส่วนประกอบไว้ที่นี่?


4
Angular ใช้ entryComponents เพื่อเปิดใช้งาน "tree Shake" กล่าวคือรวบรวมเฉพาะส่วนประกอบที่ใช้จริงในโครงการแทนที่จะรวบรวมส่วนประกอบทั้งหมดที่อยู่declaredในngModuleแต่ไม่เคยใช้ angular.io/docs/ts/latest/cookbook/… entrycomponents -
ซามาร์

คำตอบ:


155

ViewContainerRef.createComponent()นี่คือสำหรับส่วนประกอบเพิ่มแบบไดนามิกที่มีการเพิ่มการใช้ การเพิ่มเข้าไปเพื่อentryComponentsบอกให้คอมไพเลอร์แม่แบบออฟไลน์รวบรวมและสร้างโรงงานให้

คอมโพเนนต์ที่ลงทะเบียนในการกำหนดค่าเส้นทางจะถูกเพิ่มโดยอัตโนมัติentryComponentsเช่นกันเนื่องจากrouter-outletยังใช้ViewContainerRef.createComponent()เพื่อเพิ่มส่วนประกอบที่กำหนดเส้นทางไปยัง DOM

คอมไพเลอร์แม่แบบออฟไลน์ (OTC) สร้างส่วนประกอบที่ใช้จริงเท่านั้น หากไม่ได้ใช้ส่วนประกอบในเทมเพลตโดยตรง OTC จะไม่สามารถทราบได้ว่าจำเป็นต้องรวบรวมหรือไม่ ด้วย entryComponents คุณสามารถบอก OTC ให้รวบรวมส่วนประกอบนี้เพื่อให้พร้อมใช้งานในรันไทม์

องค์ประกอบรายการคืออะไร? (angular.io)

เอกสาร NgModule (angular.io)

กำหนดส่วนประกอบที่ควรคอมไพล์เช่นกันเมื่อกำหนดองค์ประกอบนี้ สำหรับส่วนประกอบแต่ละรายการที่นี่ Angular จะสร้าง ComponentFactory และเก็บไว้ใน ComponentFactoryResolver

หากคุณไม่แสดงรายการส่วนประกอบที่เพิ่มแบบไดนามิกentryComponentsคุณจะได้รับข้อความแสดงข้อผิดพลาดเกี่ยวกับโรงงานที่หายไปเนื่องจาก Angular ไม่ได้สร้างขึ้น

ดูเพิ่มเติมที่https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html


12
พูดตรงไปตรงมาฉันรู้ว่าคำตอบที่ถูกต้อง 100% แต่กลับเป็นคนโกหกสำหรับฉันคุณช่วยอธิบายเพิ่มเติมได้ไหม
Pankaj Parkar

26
ยากที่จะบอกว่ามีอะไรไม่ชัดเจน คอมไพเลอร์แม่แบบออฟไลน์ (OTC) สร้างส่วนประกอบที่ใช้จริงเท่านั้น หากไม่ได้ใช้ส่วนประกอบในเทมเพลตโดยตรง OTC จะไม่สามารถทราบได้ว่าจำเป็นต้องรวบรวมหรือไม่ ด้วยentryComponentsคุณสามารถบอก OTC ให้รวบรวมส่วนประกอบนี้เพื่อให้พร้อมใช้งานที่รันไทม์
GünterZöchbauer

3
stackoverflow.com/questions/36325212/…จะเป็นตัวอย่าง
GünterZöchbauer

2
โดยทั่วไปแล้วถ้ามีรายการ component อยู่ในdeclarationsนั้นก็ควรอยู่ในรายการentryComponentsด้วยใช่ไหม?
omnomnom

1
เฉพาะในกรณีที่มีการเพิ่มส่วนประกอบแบบไดนามิกcreateComponentในโค้ดของคุณหรือตัวอย่างเช่นเราเตอร์ที่ใช้ thod API เพื่อเพิ่มส่วนประกอบ
GünterZöchbauer

30

คุณจะไม่ได้รับคำอธิบายที่ดีกว่าเอกสารเชิงมุม: รายการส่วนประกอบและngmodule คำถามที่พบบ่อย

และด้านล่างนี้คือคำอธิบายจากเอกสารเชิงมุม

ส่วนประกอบรายการคือส่วนประกอบใด ๆ ที่โหลดเชิงมุมโดยจำเป็นตามประเภท

ส่วนประกอบที่โหลดอย่างเปิดเผยผ่านตัวเลือกไม่ใช่ส่วนประกอบรายการ

ส่วนประกอบของแอปพลิเคชันส่วนใหญ่จะโหลดอย่างเปิดเผย Angular ใช้ตัวเลือกของคอมโพเนนต์เพื่อค้นหาองค์ประกอบในเทมเพลต จากนั้นจะสร้างการแสดง HTML ของส่วนประกอบและแทรกลงใน DOM ที่องค์ประกอบที่เลือก สิ่งเหล่านี้ไม่ใช่ส่วนประกอบรายการ

คอมโพเนนต์บางส่วนจะโหลดแบบไดนามิกเท่านั้นและจะไม่ถูกอ้างอิงในเทมเพลตคอมโพเนนต์

bootstrapped root AppComponentเป็นส่วนประกอบรายการ จริงตัวเลือกตรงกับแท็กองค์ประกอบใน index.html แต่index.htmlไม่ใช่เทมเพลตคอมโพเนนต์และAppComponentตัวเลือกไม่ตรงกับองค์ประกอบในเทมเพลตส่วนประกอบใด ๆ

Angular โหลด AppComponent แบบไดนามิกเนื่องจากมีการแสดงรายการตามประเภท@NgModule.bootstrapหรือเพิ่มขึ้นโดยจำเป็นด้วยวิธีการ ngDoBootstrap ของโมดูล

ส่วนประกอบในนิยามเส้นทางยังเป็นส่วนประกอบรายการ นิยามเส้นทางหมายถึงส่วนประกอบตามประเภท เราเตอร์จะละเว้นตัวเลือกของส่วนประกอบที่กำหนดเส้นทาง (หากมี) และโหลดส่วนประกอบแบบไดนามิกในไฟล์RouterOutlet.

คอมไพลเลอร์ไม่สามารถค้นพบส่วนประกอบรายการเหล่านี้ได้โดยการค้นหาในเทมเพลตส่วนประกอบอื่น ๆ คุณต้องบอกเกี่ยวกับพวกเขาโดยเพิ่มลงในentryComponentsรายการ

Angular จะเพิ่มส่วนประกอบประเภทต่อไปนี้โดยอัตโนมัติในโมดูลentryComponents:

  • ส่วนประกอบใน@NgModule.bootstrapรายการ
  • ส่วนประกอบที่อ้างอิงในการกำหนดค่าเราเตอร์

คุณไม่จำเป็นต้องพูดถึงส่วนประกอบเหล่านี้อย่างชัดเจนแม้ว่าการทำเช่นนั้นจะไม่เป็นอันตรายก็ตาม


ตอนนี้เอกสารเชิงมุมไม่สามารถใช้งานได้ดังนั้นขอขอบคุณสำหรับสิ่งนั้น!
Caelum

ดูเหมือนจะไม่ได้กล่าวถึงส่วนประกอบในการกำหนดค่าเส้นทางจะถูกเพิ่มลงใน entryComponents โดยอัตโนมัติ (ดังนั้นคุณจึงไม่จำเป็นต้องกำหนด)
Connor

1
ถ้าเราสร้างส่วนประกอบที่จะใช้เป็นEntryComponentเราควรลบselectorแอตทริบิวต์? (เนื่องจากจะไม่ใช้)
Ronan

24

คำตอบอื่น ๆ กล่าวถึงสิ่งนี้ แต่สรุปพื้นฐานคือ:

  • จำเป็นเมื่อไม่ได้ใช้คอมโพเนนต์ภายในเทมเพลต html <my-component />
  • ตัวอย่างเช่นเมื่อใช้ส่วนประกอบกล่องโต้ตอบ Angular Material คุณจะใช้ส่วนประกอบนั้นโดยอ้อม

ส่วนประกอบกล่องโต้ตอบ Material ถูกสร้างขึ้นภายในรหัส TS ไม่ใช่เทมเพลต:

    const dialogRef = this.dialog.open(MyExampleDialog, { width: '250px' });
  }

สิ่งนี้ต้องการให้คุณลงทะเบียนเป็น entryComponent:

  • entryComponents: [MyExampleDialog]

มิฉะนั้นคุณจะได้รับข้อผิดพลาด:

  • ERROR Error: No component factory found for MyExampleDialog. Did you add it to @NgModule.entryComponents?

2
คำอธิบายที่ดีที่สุดตรงนี้
nop

3

อาร์เรย์ entryComponents ใช้เพื่อกำหนดเฉพาะคอมโพเนนต์ที่ไม่พบใน html และสร้างแบบไดนามิก Angular ต้องการคำใบ้นี้เพื่อค้นหาส่วนประกอบรายการและรวบรวม

ส่วนประกอบรายการหลักมีสองประเภท:

  • คอมโพเนนต์ root bootstrapped
  • องค์ประกอบที่คุณระบุในนิยามเส้นทาง

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับส่วนประกอบรายการโปรดดูที่ angular.io https://angular.io/guide/entry-components


1

ความเป็นมาเล็กน้อยเกี่ยวกับ entryComponent

entryComponentเป็นส่วนประกอบใด ๆ โหลดเชิงมุมที่จำเป็น คุณสามารถประกาศentryComponentโดยการบูตเครื่องในNgModuleหรือในข้อกำหนดเส้นทาง

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent] // bootstrapped entry component
})

เอกสารระบุด้านล่าง

ในการเปรียบเทียบส่วนประกอบทั้งสองประเภทมีส่วนประกอบที่รวมอยู่ในเทมเพลตซึ่งมีการประกาศ นอกจากนี้ยังมีส่วนประกอบที่คุณจำเป็นต้องโหลด; นั่นคือส่วนประกอบรายการ

ตอนนี้เพื่อตอบคำถามเฉพาะของคุณเกี่ยวกับ entryComponents

มีentryComponentsอาร์เรย์ใน@NgModuleไฟล์ คุณสามารถใช้เพื่อเพิ่มentryComponentsหากองค์ประกอบเป็น bootstrapped ViewContainerRef.createComponent()ใช้

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

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(myComp.component);
const viewContainerRef = this.compHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);

0

เนื่องจาก Angular 9 entryComponentsไม่จำเป็นต้องใช้อีกต่อไปเนื่องจาก Ivy อนุญาตให้เลิกใช้คุณลักษณะนี้และสามารถลบออกจากการประกาศโมดูลได้

API และคุณสมบัติที่เลิกใช้งาน - entryComponentsและANALYZE_FOR_ENTRY_COMPONENTSไม่จำเป็นอีกต่อไป

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

ไอวี่เชิงมุม

Ivy เป็นชื่อรหัสสำหรับการคอมไพล์และการแสดงผลรุ่นต่อไปของ Angular ด้วย Angular เวอร์ชัน 9 เวอร์ชัน 9 คำสั่งคอมไพลเลอร์และรันไทม์ใหม่จะถูกใช้โดยค่าเริ่มต้นแทนคอมไพลเลอร์และรันไทม์รุ่นเก่าที่เรียกว่า View Engine

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