การประกาศผู้ให้บริการและการนำเข้าใน NgModule แตกต่างกันอย่างไร


คำตอบ:


516

แนวคิดเชิงมุม

  • imports ทำให้การประกาศที่ถูกเอ็กซ์พอร์ตของโมดูลอื่นพร้อมใช้งานในโมดูลปัจจุบัน
  • declarationsจะทำให้คำสั่ง (รวมถึงส่วนประกอบและท่อ) จากโมดูลปัจจุบันพร้อมใช้งานกับคำสั่งอื่น ๆ ในโมดูลปัจจุบัน ตัวเลือกคำสั่งส่วนประกอบหรือท่อจะจับคู่กับ HTML เท่านั้นหากมีการประกาศหรือนำเข้า
  • providersเพื่อให้บริการและค่านิยมที่รู้จักกับ DI (การฉีดพึ่งพา) พวกเขาจะถูกเพิ่มเข้าไปในขอบเขตของรูทและถูกส่งไปยังบริการหรือคำสั่งอื่น ๆ ที่มีการพึ่งพา

กรณีพิเศษสำหรับprovidersโมดูลที่โหลดขี้เกียจที่ได้รับหัวฉีดลูกของตัวเอง providersของโมดูลที่โหลดแบบ lazy ถูกจัดเตรียมไว้ให้กับโมดูลที่โหลดแบบ lazy นี้โดยดีฟอลต์ (ไม่ใช่แอ็พพลิเคชันทั้งหมดเช่นเดียวกับโมดูลอื่น ๆ )

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับโมดูลโปรดดูที่https://angular.io/docs/ts/latest/guide/ngmodule.html

  • exportsทำให้ส่วนประกอบคำสั่งและไพพ์พร้อมใช้งานในโมดูลที่เพิ่มโมดูลimportsนี้ exportsยังสามารถใช้เพื่อส่งออกโมดูลอีกครั้งเช่น CommonModule และ FormsModule ซึ่งมักจะทำในโมดูลที่ใช้ร่วมกัน

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

TypeScript (ES2015) นำเข้า

import ... from 'foo/bar'(ซึ่งอาจแก้ไขให้index.ts ) มีไว้สำหรับการนำเข้า TypeScript คุณต้องการสิ่งเหล่านี้ทุกครั้งที่คุณใช้ตัวระบุในไฟล์ typescript ที่ถูกประกาศในไฟล์ typescript อื่น

ของเชิงมุม @NgModule() importsและ typescript importมีแนวความคิดที่แตกต่างกันอย่างสิ้นเชิง

ดูเพิ่มเติมที่jDriven - ไวยากรณ์การนำเข้า TypeScript และ ES6

ส่วนใหญ่เป็นไวยากรณ์โมดูล ECMAScript 2015 (ES6) ธรรมดาที่ TypeScript ใช้เช่นกัน


1
ฉันคิดว่า แต่ฉันไม่แน่ใจว่าคำแนะนำล่าสุดคือการใส่ผู้ให้บริการแอพใน CoreModule แทนที่จะใช้forRoot()ในโมดูลที่โหลดช้า คุณเห็นด้วยหรือไม่? ดูแกนโมดูล ไม่มีลิงก์ไปยัง # shared-module-for-root อีกต่อไป
Mark Rajcok

1
คำอธิบายที่ยอดเยี่ยม ขอบคุณ @ günter-zöchbauer พูดถึงเพียงว่า afaik importเป็นฟังก์ชั่น JS (ES2015) ไม่ใช่ TypeScript หนึ่ง :)
cassi.lup

และอะไรคือการส่งออก [] ใน NgModule ดูดเหมือนการส่งออก: [MatCheckBox]
Omar

4
จะซื่อสัตย์ผมคิดว่าการออกแบบของ NgModule ของเชิงมุมเป็นเงอะงะและปิดบังเปรียบเทียบกับVueและตอบสนอง คุณต้องการนำเข้าโมดูลอื่น ๆ ที่มีimportsแต่การส่งออกต้องแจ้งคุณ (องค์ประกอบสั่งท่อ) exportsด้วย ดังนั้นเป้าหมายหลักของimportsและexportsแตกต่างกันคือ แต่เป้าหมายที่สำคัญของการเป็นคุณexports declarationsคุณประกาศส่วนประกอบของคุณด้วยdeclarationsแต่สำหรับองค์ประกอบที่โหลดแบบไดนามิกคุณต้องใส่องค์ประกอบเหล่าentryComponentsนั้น ในขณะเดียวกันการprovidersจัดการในเรื่องอื่นโดย DI
xuemind

1
คำตอบที่ซับซ้อนที่อธิบายถึงกรอบการทำงานที่ซับซ้อน
Donato

85

imports ใช้เพื่ออิมพอร์ตโมดูลที่สนับสนุนเช่น FormsModule, RouterModule, CommonModule หรือโมดูลคุณลักษณะที่กำหนดเองอื่น ๆ

declarationsใช้ในการประกาศส่วนประกอบคำสั่งท่อที่เป็นของโมดูลปัจจุบัน ทุกคนภายในการประกาศรู้ซึ่งกันและกัน ตัวอย่างเช่นหากเรามีส่วนประกอบให้พูดชื่อผู้ใช้งานซึ่งแสดงรายการชื่อผู้ใช้และเรายังมีไพพ์เช่นกันพูดว่า toupperPipe ซึ่งแปลงสตริงเป็นสตริงตัวอักษรตัวพิมพ์ใหญ่ ตอนนี้ถ้าเราต้องการแสดงชื่อผู้ใช้ด้วยตัวอักษรตัวพิมพ์ใหญ่ในชื่อผู้ใช้ของเราเราสามารถใช้ toupperPipe ซึ่งเราได้สร้างไว้ก่อนหน้านี้ แต่คำถามคือ UsernameComponent รู้ได้อย่างไรว่า toupperPipe นั้นมีอยู่จริงและสามารถเข้าถึงและใช้งานได้อย่างไร การประกาศมาที่นี่เราสามารถประกาศชื่อผู้ใช้ส่วนประกอบและ toupperPipe

Providers ใช้สำหรับฉีดบริการตามที่ต้องการโดยส่วนประกอบคำสั่งท่อในโมดูล


3
"declarations: ใช้เพื่อประกาศส่วนประกอบคำสั่งท่อที่เป็นของโมดูลปัจจุบันทุกอย่างที่อยู่ภายในการประกาศรู้ซึ่งกันและกัน" นี่ควรเป็นคำตอบที่
ดี

60

ประกาศส่วนประกอบแล้วนำเข้าโมดูลและให้บริการ ตัวอย่างฉันกำลังทำงานกับ:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';


import { AppComponent } from './app.component';
import {FormsModule} from '@angular/forms';
import { UserComponent } from './components/user/user.component';
import { StateService } from './services/state.service';    

@NgModule({
  declarations: [
    AppComponent,
    UserComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [ StateService ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

3
ฉันชอบความเรียบง่ายของคำอธิบายนี้ แต่ทำให้ฉันสงสัยว่าทำไมไม่มีคุณสมบัติ "stuffsThisComponentNeeds" เพียงรายการเดียว ดูเหมือนว่าพวกเขาทั้งหมดกำลังจัดการกับสิ่งเดียวกันซึ่งทำให้ชิ้นส่วนอื่น ๆ ของรหัสที่มีอยู่ในองค์ประกอบปัจจุบัน
redOctober13

1
@ redOctober13 ฉันเห็นด้วย ใน Node.js ทุกอย่างจะถูกนำเข้าในลักษณะเดียวกันโดยไม่คำนึงว่าเป็นรุ่นฐานข้อมูลโมดูลบริการหรือแพคเกจของบุคคลที่สามที่ติดตั้ง และฉันก็คิดเช่นเดียวกันว่าเกิดขึ้นกับ reactJS
SanSolo

18

@NgModuleโครงสร้างเชิงมุม:

  1. import { x } from 'y';: นี่คือไวยากรณ์ typescript มาตรฐาน ( ES2015/ES6ไวยากรณ์โมดูล) สำหรับการนำเข้ารหัสจากไฟล์อื่น ๆ นี้ไม่ได้เป็นเฉพาะเชิงมุม นอกจากนี้เทคนิคนี้ไม่ได้เป็นส่วนหนึ่งของโมดูลมันก็แค่จำเป็นต้องได้รับรหัสที่จำเป็นภายในขอบเขตของไฟล์นี้
  2. imports: [FormsModule]: คุณนำเข้าโมดูลอื่น ๆ ได้ที่นี่ ตัวอย่างเช่นเรานำเข้าFormsModuleในตัวอย่างด้านล่าง ตอนนี้เราสามารถใช้ฟังก์ชันการทำงานที่ FormsModule มีให้ในโมดูลนี้
  3. declarations: [OnlineHeaderComponent, ReCaptcha2Directive]: คุณใส่ส่วนประกอบคำสั่งและท่อที่นี่ เมื่อประกาศที่นี่คุณสามารถใช้งานได้ตลอดทั้งโมดูล ตัวอย่างเช่นตอนนี้เราสามารถใช้OnlineHeaderComponentในAppComponentมุมมอง (ไฟล์ html) Angular รู้ว่าจะหาได้ที่ไหนOnlineHeaderComponentเพราะมันถูกประกาศใน@NgModule.
  4. providers: [RegisterService]: ที่นี่บริการของเราของโมดูลเฉพาะนี้มีการกำหนดไว้ คุณสามารถใช้บริการในองค์ประกอบของคุณโดยการฉีดด้วยการฉีดพึ่งพา

โมดูลตัวอย่าง:

// Angular
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

// Components
import { AppComponent } from './app.component';
import { OfflineHeaderComponent } from './offline/offline-header/offline-header.component';
import { OnlineHeaderComponent } from './online/online-header/online-header.component';

// Services
import { RegisterService } from './services/register.service';

// Directives
import { ReCaptcha2Directive } from './directives/re-captcha2.directive';

@NgModule({
  declarations: [
    OfflineHeaderComponent,,
    OnlineHeaderComponent,
    ReCaptcha2Directive,
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
  ],
  providers: [
    RegisterService,
  ],
  entryComponents: [
    ChangePasswordComponent,
    TestamentComponent,
    FriendsListComponent,
    TravelConfirmComponent
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

10

เพิ่มแผ่นโกงอย่างรวดเร็วที่อาจช่วยหลังจากหยุดยาวด้วย Angular:


ประกาศ

ตัวอย่าง:

declarations: [AppComponent]

เราฉีดอะไรที่นี่? ส่วนประกอบท่อคำสั่ง


การนำเข้า

ตัวอย่าง:

imports: [BrowserModule, AppRoutingModule]

เราฉีดอะไรที่นี่? โมดูลอื่น ๆ


ผู้ให้บริการ

ตัวอย่าง:

providers: [UserService]

เราฉีดอะไรที่นี่? บริการ


บูต

ตัวอย่าง:

bootstrap: [AppComponent]

เราฉีดอะไรที่นี่? คอมโพเนนต์หลักที่จะสร้างขึ้นโดยโมดูลนี้ (โหนดพาเรนต์บนสุดสำหรับทรีคอมโพเนนต์)


ส่วนประกอบของรายการ

ตัวอย่าง:

entryComponents: [PopupComponent]

เราฉีดอะไรที่นี่? ส่วนประกอบที่สร้างขึ้นแบบไดนามิก (เช่นโดยใช้ ViewContainerRef.createComponent ())


ส่งออก

ตัวอย่าง:

export: [TextDirective, PopupComponent, BrowserModule]

เราฉีดอะไรที่นี่? ส่วนประกอบคำสั่งโมดูลหรือท่อที่เราต้องการให้เข้าถึงได้ในโมดูลอื่น (หลังจากนำเข้าโมดูลนี้)


1
เกี่ยวกับการส่งออก
lugte098

@ lugte098 ฉันได้เพิ่มการส่งออกเป็นรายการนี้
Przemek Struciński

ฉันชอบเลย์เอาต์นี้สำหรับคำอธิบายซึ่งย่อยง่ายมาก ขอบคุณ!
แอรอนจอร์แดน

1
  1. ประกาศ : คุณสมบัตินี้บอกเกี่ยวกับส่วนประกอบคำสั่งและท่อที่เป็นของโมดูลนี้
  2. การส่งออก : ส่วนย่อยของการประกาศที่ควรจะมองเห็นและใช้งานได้ในแม่แบบองค์ประกอบของ NgModules อื่น ๆ
  3. อิมพอร์ต : โมดูลอื่นที่ต้องการคลาสที่เอ็กซ์พอร์ตโดยเท็มเพลตคอมโพเนนต์ที่ประกาศใน NgModule นี้
  4. ผู้ให้บริการ : ผู้สร้างบริการที่ NgModule นี้มีส่วนช่วยในการรวบรวมบริการทั่วโลก; พวกเขาสามารถเข้าถึงได้ในทุกส่วนของแอพ (นอกจากนี้คุณยังสามารถระบุผู้ให้บริการในระดับองค์ประกอบซึ่งมักเป็นที่ต้องการ)
  5. bootstrap : มุมมองแอปพลิเคชันหลักเรียกว่าองค์ประกอบหลักซึ่งโฮสต์มุมมองแอพอื่นทั้งหมด เฉพาะ NgModule รูทควรตั้งค่าคุณสมบัติ bootstrap
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.