Beberapa Tips Sudut

Waktu yang cukup telah berlalu sejak rilis Angular yang diperbarui. Saat ini, banyak proyek telah selesai. Dari "memulai" banyak pengembang telah pindah ke penggunaan yang berarti dari kerangka kerja ini, kemampuannya, dan belajar cara melewati jebakan. Setiap pengembang dan / atau tim telah membentuk panduan gaya dan praktik terbaik mereka sendiri, atau mereka menggunakan yang lain. Tetapi pada saat yang sama, Anda sering harus berurusan dengan banyak kode Angular, yang tidak menggunakan banyak fitur dari kerangka kerja ini dan / atau ditulis dalam gaya AngularJS.


Artikel ini menyajikan beberapa fitur dan fitur menggunakan kerangka Angular, yang, menurut pendapat sederhana penulis, tidak tercakup secara memadai dalam manual atau tidak digunakan oleh pengembang. Artikel ini membahas penggunaan permintaan HTTP "Interceptors", penggunaan Route Guard untuk membatasi akses ke pengguna. Beberapa rekomendasi untuk menggunakan RxJS dan mengelola status aplikasi diberikan. Juga disajikan beberapa rekomendasi tentang desain kode proyek, yang mungkin akan membuat kode proyek lebih bersih dan lebih mudah dipahami. Penulis berharap artikel ini bermanfaat tidak hanya bagi pengembang yang baru mulai berkenalan dengan Angular, tetapi juga bagi pengembang yang berpengalaman.


Bekerja dengan HTTP


Pembangunan aplikasi Web klien apa pun dilakukan berdasarkan permintaan HTTP ke server. Bagian ini membahas beberapa fitur dari kerangka Angular untuk bekerja dengan permintaan HTTP.


Menggunakan Interceptor


Dalam beberapa kasus, mungkin perlu memodifikasi permintaan sebelum mencapai server. Atau Anda perlu mengubah setiap jawaban. Dimulai dengan Angular 4.3, HttpClient baru telah dirilis. Itu menambahkan kemampuan untuk mencegat permintaan menggunakan pencegat (Ya, mereka akhirnya dikembalikan hanya dalam versi 4.3!, Ini adalah salah satu fitur yang hilang dari AngularJs yang diharapkan tidak bermigrasi ke Angular). Ini adalah semacam middleware antara http-api dan permintaan aktual.


Satu kasus penggunaan umum mungkin otentikasi. Untuk mendapatkan respons dari server, Anda sering perlu menambahkan semacam mekanisme otentikasi ke permintaan. Tugas ini menggunakan pencegat diselesaikan cukup sederhana:


import { Injectable } from "@angular/core"; import { Observable } from "rxjs/Observable"; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from @angular/common/http"; @Injectable() export class JWTInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { req = req.clone({ setHeaders: { authorization: localStorage.getItem("token") } }); return next.handle(req); } } 

Karena aplikasi dapat memiliki beberapa pencegat, mereka disusun dalam sebuah rantai. Elemen pertama disebut dengan kerangka Angular itu sendiri. Selanjutnya, kami bertanggung jawab untuk mengirimkan permintaan ke pencegat berikutnya. Untuk melakukan ini, kami memanggil metode pegangan elemen berikutnya dalam rantai segera setelah kami selesai. Kami menghubungkan interceptor:


 import { BrowserModule } from "@angular/platform-browser"; import { NgModule } from "@angular/core"; import { AppComponent } from "./app.component"; import { HttpClientModule } from "@angular/common/http"; import { HTTP_INTERCEPTORS } from "@angular/common/http"; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, HttpClientModule], providers: [ { provide: HTTP_INTERCEPTORS, useClass: JWTInterceptor, multi: true } ], bootstrap: [AppComponent] }) export class AppModule {} 

Seperti yang Anda lihat, koneksi dan implementasi interceptor cukup sederhana.


Pelacakan kemajuan


Salah satu fitur dari HttpClient adalah kemampuan untuk melacak kemajuan permintaan. Misalnya, jika Anda perlu mengunduh file besar, maka Anda mungkin ingin melaporkan perkembangan unduhan ke pengguna. Untuk mendapatkan kemajuan, Anda harus mengatur properti reportProgress dari objek HttpRequest menjadi true . Contoh layanan yang mengimplementasikan pendekatan ini:


 import { Observable } from "rxjs/Observable"; import { HttpClient } from "@angular/common/http"; import { Injectable } from "@angular/core"; import { HttpRequest } from "@angular/common/http"; import { Subject } from "rxjs/Subject"; import { HttpEventType } from "@angular/common/http"; import { HttpResponse } from "@angular/common/http"; @Injectable() export class FileUploadService { constructor(private http: HttpClient) {} public post(url: string, file: File): Observable<number> { var subject = new Subject<number>(); const req = new HttpRequest("POST", url, file, { reportProgress: true }); this.httpClient.request(req).subscribe(event => { if (event.type === HttpEventType.UploadProgress) { const percent = Math.round((100 * event.loaded) / event.total); subject.next(percent); } else if (event instanceof HttpResponse) { subject.complete(); } }); return subject.asObservable(); } } 

Metode posting mengembalikan Observable yang mewakili kemajuan pengunduhan. Yang diperlukan sekarang adalah menampilkan progres pemuatan di dalam komponen.


Routing Menggunakan Route Guard


Routing memungkinkan Anda memetakan permintaan aplikasi ke sumber daya tertentu dalam aplikasi. Cukup sering perlu untuk memecahkan masalah membatasi visibilitas jalur di mana komponen tertentu berada, tergantung pada beberapa kondisi. Dalam kasus ini, Angular memiliki mekanisme pembatasan transisi. Sebagai contoh, ada layanan yang akan menerapkan penjaga rute. Misalkan dalam aplikasi otentikasi pengguna diimplementasikan menggunakan JWT. Versi layanan yang disederhanakan yang memeriksa apakah pengguna berwenang dapat direpresentasikan sebagai:


 @Injectable() export class AuthService { constructor(public jwtHelper: JwtHelperService) {} public isAuthenticated(): boolean { const token = localStorage.getItem("token"); //        return !this.jwtHelper.isTokenExpired(token); } } 

Untuk menerapkan penjaga rute, Anda harus mengimplementasikan antarmuka CanActivate , yang terdiri dari satu fungsi canActivate .


 @Injectable() export class AuthGuardService implements CanActivate { constructor(public auth: AuthService, public router: Router) {} canActivate(): boolean { if (!this.auth.isAuthenticated()) { this.router.navigate(["login"]); return false; } return true; } } 

Implementasi AuthGuardService menggunakan AuthGuardService dijelaskan di atas untuk memverifikasi otorisasi pengguna. Metode canActivate mengembalikan nilai boolean yang dapat digunakan dalam kondisi aktivasi rute.


Sekarang kita bisa menerapkan Penjaga Rute yang dibuat untuk rute atau jalur apa pun. Untuk melakukan ini, ketika mendeklarasikan Routes kami menentukan layanan kami, yang mewarisi antarmuka CanActivate , di bagian canActivate :


 export const ROUTES: Routes = [ { path: "", component: HomeComponent }, { path: "profile", component: UserComponent, canActivate: [AuthGuardService] }, { path: "**", redirectTo: "" } ]; 

Dalam kasus ini, rute /profile memiliki nilai konfigurasi opsional canActivate . AuthGuard dijelaskan sebelumnya dilewatkan sebagai argumen untuk properti canActivate ini. Selanjutnya, metode canActivate akan dipanggil setiap kali seseorang mencoba mengakses jalur /profile . Jika pengguna diotorisasi, ia akan mendapatkan akses ke jalur /profile , jika tidak ia akan diarahkan ke jalur /login .


Anda harus menyadari bahwa canActivate masih memungkinkan Anda untuk mengaktifkan komponen di jalur ini, tetapi tidak memungkinkan Anda untuk beralih ke komponen itu. Jika Anda perlu melindungi aktivasi dan pemuatan komponen, maka untuk kasus ini kita dapat menggunakan canLoad . Implementasi CanLoad dapat dilakukan dengan analogi.


Memasak RxJS


Angular dibangun di atas RxJS. RxJS adalah perpustakaan untuk bekerja dengan aliran data asinkron dan berbasis peristiwa menggunakan urutan yang dapat diamati. RxJS adalah implementasi JavaScript dari ReactiveX API. Sebagian besar, kesalahan yang terjadi ketika bekerja dengan perpustakaan ini terkait dengan pengetahuan dasar tentang penerapannya.


Menggunakan async alih-alih mendaftar untuk acara


Sejumlah besar pengembang yang baru saja menggunakan kerangka Angular menggunakan fungsi subscribe Observable untuk menerima dan menyimpan data dalam komponen:


 @Component({ selector: "my-component", template: ` <span>{{localData.name}} : {{localData.value}}</span>` }) export class MyComponent { localData; constructor(http: HttpClient) { http.get("api/data").subscribe(data => { this.localData = data; }); } } 

Sebagai gantinya, kita dapat berlangganan melalui templat menggunakan pipa async:


 @Component({ selector: "my-component", template: ` <p>{{data.name | async}} : {{data.value | async}}</p>` }) export class MyComponent { data; constructor(http: HttpClient) { this.data = http.get("api/data"); } } 

Dengan berlangganan melalui templat, kami menghindari kebocoran memori karena Angular secara otomatis berhenti berlangganan dari Observable ketika komponen rusak. Dalam hal ini, untuk permintaan HTTP, menggunakan pipa async secara praktis tidak memberikan manfaat apa pun, kecuali satu - async akan membatalkan permintaan jika data tidak lagi diperlukan, dan tidak akan menyelesaikan pemrosesan permintaan.


Banyak fitur Observables tidak digunakan saat berlangganan secara manual. Perilaku yang dapat Observables dapat diperpanjang dengan mengulangi (misalnya, coba lagi dalam permintaan http), pembaruan berbasis waktu, atau pra-caching.


Gunakan $ untuk menunjukkan yang bisa diamati


Paragraf berikutnya terkait dengan desain kode sumber aplikasi dan mengikuti dari paragraf sebelumnya. Untuk membedakan Observable dari variabel sederhana, cukup sering Anda dapat mendengar saran untuk menggunakan tanda " $ " atas nama variabel atau bidang. Trik sederhana ini akan menghilangkan kebingungan dalam variabel saat menggunakan async.


 import { Component } from "@angular/core"; import { Observable } from "rxjs/Rx"; import { UserClient } from "../services/user.client"; import { User } from "../services/user"; @Component({ selector: "user-list", template: ` <ul class="user_list" *ngIf="(users$ | async).length"> <li class="user" *ngFor="let user of users$ | async"> {{ user.name }} - {{ user.birth_date }} </li> </ul>` }) export class UserList { public users$: Observable<User[]>; constructor(public userClient: UserClient) {} public ngOnInit() { this.users$ = this.client.getUsers(); } } 

Kapan berhenti berlangganan (berhenti berlangganan)


Pertanyaan paling umum yang dimiliki pengembang saat mengenal Angular secara singkat adalah kapan Anda masih harus berhenti berlangganan, dan kapan tidak. Untuk menjawab pertanyaan ini, Anda harus memutuskan jenis Observable yang saat ini digunakan. Dalam Angular ada 2 jenis yang Observable - terbatas dan tak terbatas, beberapa menghasilkan terbatas, yang lain, masing-masing, jumlah nilai tak terbatas.


Http Observable kompak, dan pendengar / pendengar acara DOM yang tak terbatas Observable .


Jika berlangganan nilai-nilai infinite Observable dilakukan secara manual (tanpa menggunakan pipa async), maka balasan harus dilakukan tanpa gagal. Jika kita berlangganan secara manual ke Observable yang terbatas, maka tidak perlu berhenti berlangganan, RxJS akan mengurus ini. Dalam hal Compact Observables kita dapat berhenti berlangganan jika Observable memiliki waktu eksekusi yang lebih lama daripada yang diperlukan, misalnya, beberapa permintaan HTTP.


Contoh Observables ringkas:


 export class SomeComponent { constructor(private http: HttpClient) { } ngOnInit() { Observable.timer(1000).subscribe(...); this.http.get("http://api.com").subscribe(...); } } 

Contoh Pengamatan Tak Terbatas


 export class SomeComponent { constructor(private element : ElementRef) { } interval: Subscription; click: Subscription; ngOnInit() { this.interval = Observable.interval(1000).subscribe(...); this.click = Observable.fromEvent(this.element.nativeElement, "click").subscribe(...); } ngOnDestroy() { this.interval.unsubscribe(); this.click.unsubscribe(); } } 

Di bawah, secara lebih rinci adalah kasus di mana Anda harus berhenti berlangganan


  1. Anda harus berhenti berlangganan dari formulir dan dari kontrol individual yang telah Anda langgani:

 export class SomeComponent { ngOnInit() { this.form = new FormGroup({...}); this.valueChangesSubs = this.form.valueChanges.subscribe(...); this.statusChangesSubs = this.form.statusChanges.subscribe(...); } ngOnDestroy() { this.valueChangesSubs.unsubscribe(); this.statusChangesSubs.unsubscribe(); } } 

  1. Router Menurut dokumentasi, Angular harus berhenti berlangganan sendiri, namun ini tidak terjadi . Karena itu, untuk menghindari masalah lebih lanjut, kami menulis sendiri:

 export class SomeComponent { constructor(private route: ActivatedRoute, private router: Router) { } ngOnInit() { this.route.params.subscribe(..); this.route.queryParams.subscribe(...); this.route.fragment.subscribe(...); this.route.data.subscribe(...); this.route.url.subscribe(..); this.router.events.subscribe(...); } ngOnDestroy() { //        observables } } 

  1. Urutan tanpa akhir. Contohnya adalah urutan yang dibuat menggunakan interva() atau pendengar acara (fromEvent()) :

 export class SomeComponent { constructor(private element : ElementRef) { } interval: Subscription; click: Subscription; ngOnInit() { this.intervalSubs = Observable.interval(1000).subscribe(...); this.clickSubs = Observable.fromEvent(this.element.nativeElement, "click").subscribe(...); } ngOnDestroy() { this.intervalSubs.unsubscribe(); this.clickSubs.unsubscribe(); } } 

takeUntil dan takeWhile


Untuk menyederhanakan pekerjaan dengan Observables tak terbatas di RxJS, ada dua fungsi yang mudah digunakan - takeUntil dan takeWhile . Mereka melakukan tindakan yang sama - berhenti berlangganan dari Observable pada akhir kondisi tertentu, perbedaannya hanya pada nilai yang diterima. takeWhile menerima boolean , dan takeUntil Subject .
Contoh takeWhile :


 export class SomeComponent implements OnDestroy, OnInit { public user: User; private alive: boolean = true; public ngOnInit() { this.userService .authenticate(email, password) .takeWhile(() => this.alive) .subscribe(user => { this.user = user; }); } public ngOnDestroy() { this.alive = false; } } 

Dalam hal ini, ketika bendera alive diubah, Observable akan berhenti berlangganan. Dalam contoh ini, berhenti berlangganan ketika komponen dihancurkan.
takeUntil contoh:


 export class SomeComponent implements OnDestroy, OnInit { public user: User; private unsubscribe: Subject<void> = new Subject(void); public ngOnInit() { this.userService.authenticate(email, password) .takeUntil(this.unsubscribe) .subscribe(user => { this.user = user; }); } public ngOnDestroy() { this.unsubscribe.next(); this.unsubscribe.complete(); } } 

Dalam hal ini, untuk berhenti berlangganan dari Observable kami melaporkan bahwa subject mengambil nilai berikutnya dan melengkapinya.


Menggunakan fungsi-fungsi ini akan menghindari kebocoran dan menyederhanakan pekerjaan dengan berhenti berlangganan data. Fungsi mana yang digunakan? Jawaban atas pertanyaan ini harus dipandu oleh preferensi pribadi dan persyaratan saat ini.


Manajemen negara dalam aplikasi Angular, @ ngrx / store


Cukup sering, ketika mengembangkan aplikasi yang kompleks, kita dihadapkan dengan kebutuhan untuk menyimpan keadaan dan menanggapi perubahannya. Ada banyak perpustakaan untuk aplikasi yang dikembangkan pada kerangka kerja ReactJs yang memungkinkan Anda untuk mengontrol keadaan aplikasi dan merespons perubahannya - Fluks, Redux, Redux-saga, dll. Untuk aplikasi Angular, ada wadah negara berbasis RxJS yang terinspirasi oleh Redux - @ ngrx / store. Pengelolaan kondisi aplikasi yang tepat akan menyelamatkan pengembang dari banyak masalah saat aplikasi diperluas.


Mengapa Redux
Redux memposisikan dirinya sebagai wadah keadaan yang dapat diprediksi untuk aplikasi JavaScript. Redux terinspirasi oleh Flux dan Elm.


Redux menyarankan untuk memikirkan aplikasi sebagai keadaan awal yang dapat dimodifikasi dengan serangkaian tindakan, yang dapat menjadi pendekatan yang baik untuk membangun aplikasi web yang kompleks.


Redux tidak terkait dengan kerangka kerja tertentu, dan meskipun dikembangkan untuk Bereaksi, ia dapat digunakan dengan Angular atau jQuery.


Postulat utama Redux:


  • satu repositori untuk seluruh status aplikasi
  • negara hanya baca
  • perubahan dilakukan oleh fungsi "murni", yang tunduk pada persyaratan berikut:
  • tidak boleh membuat panggilan eksternal melalui jaringan atau database;
  • mengembalikan nilai yang hanya bergantung pada parameter yang diteruskan;
  • argumen tidak dapat diubah, mis. fungsi seharusnya tidak mengubahnya;
  • memanggil fungsi murni dengan argumen yang sama selalu menghasilkan hasil yang sama;

Contoh fungsi manajemen negara:


 // counter.ts import { ActionReducer, Action } from "@ngrx/store"; export const INCREMENT = "INCREMENT"; export const DECREMENT = "DECREMENT"; export const RESET = "RESET"; export function counterReducer(state: number = 0, action: Action) { switch (action.type) { case INCREMENT: return state + 1; case DECREMENT: return state - 1; case RESET: return 0; default: return state; } } 

Reducer diimpor dalam modul utama aplikasi dan menggunakan fungsi StoreModule.provideStore(reducers) kami sediakan untuk injector Angular:


 // app.module.ts import { NgModule } from "@angular/core"; import { StoreModule } from "@ngrx/store"; import { counterReducer } from "./counter"; @NgModule({ imports: [ BrowserModule, StoreModule.provideStore({ counter: counterReducer }) ] }) export class AppModule { } 

Selanjutnya, layanan Store diperkenalkan ke dalam komponen dan layanan yang diperlukan. Fungsi store.select () digunakan untuk memilih status "slice":


 // app.component.ts ... interface AppState { counter: number; } @Component({ selector: "my-app", template: ` <button (click)="increment()">Increment</button> <div>Current Count: {{ counter | async }}</div> <button (click)="decrement()">Decrement</button> <button (click)="reset()">Reset Counter</button>` }) class AppComponent { counter: Observable<number>; constructor(private store: Store<AppState>) { this.counter = store.select("counter"); } increment() { this.store.dispatch({ type: INCREMENT }); } decrement() { this.store.dispatch({ type: DECREMENT }); } reset() { this.store.dispatch({ type: RESET }); } } 

@ ngrx / router-store


Dalam beberapa kasus, akan lebih mudah untuk mengaitkan keadaan aplikasi dengan rute aplikasi saat ini. Untuk kasus-kasus ini, modul @ ngrx / router-store ada. Agar aplikasi dapat menggunakan router-store untuk menghemat keadaan, cukup sambungkan routerReducer dan tambahkan panggilan ke RouterStoreModule.connectRoute di modul utama aplikasi:


 import { StoreModule } from "@ngrx/store"; import { routerReducer, RouterStoreModule } from "@ngrx/router-store"; @NgModule({ imports: [ BrowserModule, StoreModule.provideStore({ router: routerReducer }), RouterStoreModule.connectRouter() ], bootstrap: [AppComponent] }) export class AppModule { } 

Sekarang tambahkan RouterState ke status utama aplikasi:


 import { RouterState } from "@ngrx/router-store"; export interface AppState { ... router: RouterState; }; 

Selain itu, kami dapat menunjukkan status awal aplikasi saat mendeklarasikan toko:


 StoreModule.provideStore( { router: routerReducer }, { router: { path: window.location.pathname + window.location.search } } ); 

Tindakan yang didukung:


 import { go, replace, search, show, back, forward } from "@ngrx/router-store"; //      store.dispatch(go(["/path", { routeParam: 1 }], { query: "string" })); //        store.dispatch(replace(["/path"], { query: "string" })); //        store.dispatch(show(["/path"], { query: "string" })); //       store.dispatch(search({ query: "string" })); //   store.dispatch(back()); //   store.dispatch(forward()); 

UPD: Komentar menyarankan bahwa tindakan ini tidak akan tersedia di @ngrx versi baru, untuk versi baru https://github.com/ngrx/platform/blob/master/MIGRATION.md#ngrxrouter-store


Menggunakan wadah negara akan menghilangkan banyak masalah saat mengembangkan aplikasi yang kompleks. Namun, penting untuk membuat manajemen negara sesederhana mungkin. Cukup sering, kita harus berurusan dengan aplikasi di mana ada negara bersarang berlebihan, yang hanya mempersulit pemahaman aplikasi.


Organisasi Kode


Menyingkirkan ekspresi besar di import


Banyak pengembang menyadari situasi di mana ekspresi dalam import agak rumit. Ini terutama terlihat dalam aplikasi besar di mana ada banyak perpustakaan yang dapat digunakan kembali.


 import { SomeService } from "../../../core/subpackage1/subpackage2/some.service"; 

Apa lagi yang buruk dalam kode ini? Jika Anda perlu mentransfer komponen kami ke direktori lain, ekspresi dalam import tidak akan valid.


Dalam hal ini, menggunakan alias akan membuat kami dapat melepaskan diri dari ekspresi besar di import dan membuat kode kami jauh lebih bersih. Untuk menyiapkan proyek untuk menggunakan alias, Anda perlu menambahkan properti baseUrl dan path di tsconfig.json :


 / tsconfig.json { "compilerOptions": { ... "baseUrl": "src", "paths": { "@app/*": ["app/*"], "@env/*": ["environments/*"] } } } 

Dengan perubahan ini, cukup mudah untuk mengelola plug-in:


 import { Component, OnInit } from "@angular/core"; import { Observable } from "rxjs/Observable"; /*    */ import { SomeService } from "@app/core"; import { environment } from "@env/environment"; /*      */ import { LocalService } from "./local.service"; @Component({ /* ... */ }) export class ExampleComponent implements OnInit { constructor( private someService: SomeService, private localService: LocalService ) { } } 

Dalam contoh ini, SomeService diimpor langsung dari @app/core bukan ekspresi besar (mis. @app/core/some-package/some.service ). Ini dimungkinkan berkat re-ekspor komponen publik di file index.ts utama. Dianjurkan untuk membuat file index.ts untuk setiap paket di mana Anda perlu mengekspor kembali semua modul publik:


 // index.ts export * from "./core.module"; export * from "./auth/auth.service"; export * from "./user/user.service"; export * from "./some-service/some.service"; 

Modul Inti, Bersama, dan Fitur


Untuk manajemen komponen aplikasi yang lebih fleksibel, cukup sering direkomendasikan dalam literatur dan berbagai sumber daya Internet untuk menyebarkan visibilitas komponennya. Dalam hal ini, pengelolaan komponen aplikasi disederhanakan. Pemisahan berikut ini paling umum digunakan: Modul Core, Shared, dan Feature.


Coremodule


Tujuan utama CoreModule adalah untuk menggambarkan layanan yang akan memiliki satu contoh untuk seluruh aplikasi (mis., Menerapkan pola tunggal). Ini sering termasuk layanan otorisasi atau layanan untuk mendapatkan informasi pengguna. Contoh CoreModule:


 import { NgModule, Optional, SkipSelf } from "@angular/core"; import { CommonModule } from "@angular/common"; import { HttpClientModule } from "@angular/common/http"; /*  */ import { SomeSingletonService } from "./some-singleton/some-singleton.service"; @NgModule({ imports: [CommonModule, HttpClientModule], declarations: [], providers: [SomeSingletonService] }) export class CoreModule { /*   CoreModule    NgModule the AppModule */ constructor( @Optional() @SkipSelf() parentModule: CoreModule ) { if (parentModule) { throw new Error("CoreModule is already loaded. Import only in AppModule"); } } } 

Sharedmodule


Modul ini menjelaskan komponen-komponen sederhana. Komponen-komponen ini tidak mengimpor atau menyuntikkan dependensi dari modul lain ke dalam konstruktornya. Mereka harus menerima semua data melalui atribut dalam templat komponen. SharedModule tidak memiliki ketergantungan pada sisa aplikasi kami, juga merupakan tempat yang ideal untuk mengimpor dan mengekspor kembali komponen Bahan Sudut atau pustaka UI lainnya.


 import { NgModule } from "@angular/core"; import { CommonModule } from "@angular/common"; import { FormsModule } from "@angular/forms"; import { MdButtonModule } from "@angular/material"; /*  */ import { SomeCustomComponent } from "./some-custom/some-custom.component"; @NgModule({ imports: [CommonModule, FormsModule, MdButtonModule], declarations: [SomeCustomComponent], exports: [ /*  Angular Material*/ CommonModule, FormsModule, MdButtonModule, /*   */ SomeCustomComponent ] }) export class SharedModule { } 

Kode fitur


Di sini Anda dapat mengulangi panduan gaya Angular. FeatureModule terpisah dibuat untuk setiap fungsi aplikasi independen. FeatureModule harus mengimpor layanan hanya dari CoreModule . Jika beberapa modul perlu mengimpor layanan dari modul lain, ada kemungkinan bahwa layanan ini harus dipindahkan ke CoreModule .


Dalam beberapa kasus, ada kebutuhan untuk menggunakan layanan hanya oleh beberapa modul dan tidak perlu mengekspornya ke CoreModule . Dalam hal ini, Anda dapat membuat SharedModule khusus, yang hanya akan digunakan dalam modul ini.
, — , - , , CoreModule , SharedModule .


, . , . , , .


Referensi


  1. https://github.com/ngrx/store
  2. http://stepansuvorov.com/blog/2017/06/angular-rxjs-unsubscribe-or-not-unsubscribe/
  3. https://medium.com/@tomastrajan/6-best-practices-pro-tips-for-angular-cli-better-developer-experience-7b328bc9db81
  4. https://habr.com/post/336280/
  5. https://angular.io/docs

Source: https://habr.com/ru/post/id425959/


All Articles