рдЕрджреНрдпрддрди рдХреЛрдгреАрдп рдХреА рд░рд┐рд╣рд╛рдИ рдХреЗ рдмрд╛рдж рдкрд░реНрдпрд╛рдкреНрдд рд╕рдордп рдмреАрдд рдЪреБрдХрд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди рдореЗрдВ, рдХрдИ рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдВ рдкреВрд░реА рд╣реЛ рдЪреБрдХреА рд╣реИрдВред "рдЖрд░рдВрдн рдХрд░рдирд╛" рд╕реЗ рдХрдИ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕ рдврд╛рдВрдЪреЗ, рдЗрд╕рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХреЗ рд╕рд╛рд░реНрдердХ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЪрд▓реЗ рдЧрдП рд╣реИрдВ, рдФрд░ рд╕реАрдЦрд╛ рд╣реИ рдХрд┐ рдиреБрдХрд╕рд╛рди рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХреИрд╕реЗ рдкрд╣реБрдВрдЪреЗрдВред рдкреНрд░рддреНрдпреЗрдХ рдбреЗрд╡рд▓рдкрд░ рдФрд░ / рдпрд╛ рдЯреАрдо рдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╕реНрдЯрд╛рдЗрд▓ рдЧрд╛рдЗрдб рдФрд░ рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда рдЕрднреНрдпрд╛рд╕ рдХрд╛ рдЧрдарди рдХрд┐рдпрд╛ рд╣реИ, рдпрд╛ рд╡реЗ рджреВрд╕рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ, рдЖрдкрдХреЛ рдЕрдХреНрд╕рд░ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХреЛрдгреАрдп рдХреЛрдб рд╕реЗ рдирд┐рдкрдЯрдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ, рдЬреЛ рдЗрд╕ рдврд╛рдВрдЪреЗ рдХреА рдХрдИ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ / рдпрд╛ рдХреЛрдгреАрдпреБрд▓рд░ рдХреА рд╢реИрд▓реА рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдпрд╣ рд▓реЗрдЦ рдПрдВрдЧреБрд▓рд░ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреБрдЫ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдФрд░ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рд▓реЗрдЦрдХ рдХреА рдорд╛рдореВрд▓реА рд░рд╛рдп рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдореИрдиреБрдЕрд▓ рдореЗрдВ рдкрд░реНрдпрд╛рдкреНрдд рд░реВрдк рд╕реЗ рдХрд╡рд░ рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдпрд╛ рдбреЗрд╡рд▓рдкрд░реНрд╕ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдЖрд▓реЗрдЦ "рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░реНрд╕" HTTP рдЕрдиреБрд░реЛрдзреЛрдВ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░реВрдЯ рдЧрд╛рд░реНрдб рдХреЗ рдЙрдкрдпреЛрдЧ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рддрд╛ рд╣реИред RxJS рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдФрд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд░рд╛рдЬреНрдп рдХреЗ рдкреНрд░рдмрдВрдзрди рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕рд┐рдлрд╛рд░рд┐рд╢реЗрдВ рджреА рдЧрдИ рд╣реИрдВред рдкреНрд░рд╕реНрддреБрдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛрдб рдХреЗ рдбрд┐рдЬрд╛рдЗрди рдкрд░ рдХреБрдЫ рд╕рд┐рдлрд╛рд░рд┐рд╢реЗрдВ рджреА рдЧрдИ рд╣реИрдВ, рдЬреЛ рд╕рдВрднрд╡рддрдГ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛрдб рдХреЛ рдХреНрд▓реАрдирд░ рдФрд░ рдЕрдзрд┐рдХ рд╕рдордЭрдиреЗ рдпреЛрдЧреНрдп рдмрдирд╛рдПрдВрдЧреАред рд▓реЗрдЦрдХ рдХреЛ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рд▓реЗрдЦ рди рдХреЗрд╡рд▓ рдЙрди рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ рдЬреЛ рд╕рд┐рд░реНрдл рдПрдВрдЧреБрд▓рд░ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реЛрдирд╛ рд╢реБрд░реВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рдЕрдиреБрднрд╡реА рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рднреАред
HTTP рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВ
рдХрд┐рд╕реА рднреА рдХреНрд▓рд╛рдЗрдВрдЯ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдирд┐рд░реНрдорд╛рдг рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рднрд╛рдЧ HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдгреАрдп рдврд╛рдВрдЪреЗ рдХреА рдХреБрдЫ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рддрд╛ рд╣реИред
рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╕рд░реНрд╡рд░ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдпрд╛ рдЖрдкрдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдЙрддреНрддрд░ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдПрдВрдЧреБрд▓рд░ 4.3 рд╕реЗ рд╢реБрд░реВ рд╣реЛрдХрд░, рдПрдХ рдирдпрд╛ HttpClient рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕рдиреЗ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЕрдиреБрд░реЛрдз рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЛ рдЬреЛрдбрд╝рд╛ (рд╣рд╛рдВ, рд╡реЗ рдЕрдВрдд рдореЗрдВ рдХреЗрд╡рд▓ рд╕рдВрд╕реНрдХрд░рдг 4.3 рдореЗрдВ рд╡рд╛рдкрд╕ рдЖ рдЧрдП рдереЗ!, рдпрд╣ рдПрдВрдЧреБрд▓рд░рдЬ рдХреА рд╕рдмрд╕реЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рд▓рд╛рдкрддрд╛ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдерд╛ рдЬреЛ рдПрдВрдЧреБрд▓рд░ рдХреА рдУрд░ рдкрд▓рд╛рдпрди рдирд╣реАрдВ рдХрд░рддрд╛ рдерд╛)ред рдпрд╣ http-api рдФрд░ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдиреБрд░реЛрдз рдХреЗ рдмреАрдЪ рдХрд╛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдорд┐рдбрд▓рд╡реЗрдпрд░ рд╣реИред
рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЕрдХреНрд╕рд░ рдЕрдиреБрд░реЛрдз рдореЗрдВ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХрд╛ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рддрдВрддреНрд░ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдпрд╣ рдХрд╛рд░реНрдп рдХрд╛рдлреА рд╕рд░рд▓рддрд╛ рд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
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); } }
рдХреНрдпреЛрдВрдХрд┐ рдХрд┐рд╕реА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдХрдИ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рд╡реЗ рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рд╣реЛрддреЗ рд╣реИрдВред рдкрд╣рд▓рд╛ рддрддреНрд╡ рдХреЛрдгреАрдп рдврд╛рдВрдЪреЗ рджреНрд╡рд╛рд░рд╛ рд╣реА рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрдЧрд▓реЗ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдкреНрд░реЗрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЬреИрд╕реЗ рд╣реА рд╕рдорд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВ рдЕрдЧрд▓реЗ рддрддреНрд╡ рдХреЗ рд╣реИрдВрдбрд▓ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░ рдХреЛ рдХрдиреЗрдХреНрдЯ рдХрд░рддреЗ рд╣реИрдВ:
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 {}
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯрд░ рдХрд╛ рдХрдиреЗрдХреНрд╢рди рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИред
рдкреНрд░рдЧрддрд┐ рдЯреНрд░реИрдХрд┐рдВрдЧ
HttpClient
рдХреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдЕрдиреБрд░реЛрдз рдХреА рдкреНрд░рдЧрддрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдкрдХреЛ рдПрдХ рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЖрдк рд╢рд╛рдпрдж рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдкреНрд░рдЧрддрд┐ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдкреНрд░рдЧрддрд┐ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ HttpRequest
рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА reportProgress
рд╕рдВрдкрддреНрддрд┐ рдХреЛ true
рд╕реЗрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдПрдХ рд╕реЗрд╡рд╛ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рдЬреЛ рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ:
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(); } }
рдкреЛрд╕реНрдЯ рд╡рд┐рдзрд┐ рдПрдХ Observable
рд╣реИ рдЬреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдкреНрд░рдЧрддрд┐ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреА рд╣реИред рдЕрдм рд╕рднреА рдХреА рдЬрд░реВрд░рдд рдШрдЯрдХ рдореЗрдВ рд▓реЛрдбрд┐рдВрдЧ рдкреНрд░рдЧрддрд┐ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рд╣реИред
рд░реВрдЯрд┐рдВрдЧред рдорд╛рд░реНрдЧ рд░рдХреНрд╖рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
рд░реВрдЯрд┐рдВрдЧ рдЖрдкрдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рднреАрддрд░ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдореИрдк рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЕрдХреНрд╕рд░ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдХреБрдЫ рд╢рд░реНрддреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдХреБрдЫ рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд╛рде рдкрде рдХреА рджреГрд╢реНрдпрддрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдЗрди рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдХреЛрдгреАрдп рдореЗрдВ рдПрдХ рд╕рдВрдХреНрд░рдордг рдкреНрд░рддрд┐рдмрдВрдз рддрдВрддреНрд░ рд╣реИред рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ, рдПрдХ рд╕реЗрд╡рд╛ рд╣реИ рдЬреЛ рд░реВрдЯ рдЧрд╛рд░реНрдб рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдЧреАред рдорд╛рди рд▓реЗрдВ рдХрд┐ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рдорд╛рдгреАрдХрд░рдг JWT рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕реЗрд╡рд╛ рдХрд╛ рдПрдХ рд╕рд░рд▓реАрдХреГрдд рд╕рдВрд╕реНрдХрд░рдг рдЬреЛ рдпрд╣ рдЬрд╛рдВрдЪрддрд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдзрд┐рдХреГрдд рд╣реИ рдпрд╛ рдирд╣реАрдВ:
@Injectable() export class AuthService { constructor(public jwtHelper: JwtHelperService) {} public isAuthenticated(): boolean { const token = localStorage.getItem("token");
рдорд╛рд░реНрдЧ рд░рдХреНрд╖рдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ CanActivate
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдПрдХрд▓ 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; } }
AuthGuardService
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдКрдкрд░ рд╡рд░реНрдгрд┐рдд AuthGuardService
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред canActivate
рд╡рд┐рдзрд┐ рдПрдХ рдмреВрд▓рд┐рдпрди рдорд╛рди рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд░реВрдЯ рд╕рдХреНрд░рд┐рдпрдг рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЕрдм рд╣рдо рдмрдирд╛рдП рдЧрдП рдорд╛рд░реНрдЧ рд░рдХреНрд╖рдХ рдХреЛ рдХрд┐рд╕реА рднреА рдорд╛рд░реНрдЧ рдпрд╛ рдкрде рдкрд░ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, Routes
рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╕рдордп Routes
рд╣рдо рдЕрдкрдиреА рд╕реЗрд╡рд╛ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ CanActivate
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ CanActivate
рд╣реИред
export const ROUTES: Routes = [ { path: "", component: HomeComponent }, { path: "profile", component: UserComponent, canActivate: [AuthGuardService] }, { path: "**", redirectTo: "" } ];
рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, /profile
рдорд╛рд░реНрдЧ рдореЗрдВ рд╡реИрдХрд▓реНрдкрд┐рдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдорд╛рди canActivate
ред рдкрд╣рд▓реЗ рд╡рд░реНрдгрд┐рдд AuthGuard
рдХреЛ рдЗрд╕ рд╕рдВрдкрддреНрддрд┐ рдХреЛ canActivate
рдХрд░рдиреЗ рдХреЗ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж, рдХрд┐рд╕реА рдХреЛ /profile
рдкрде рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рдкрд░ рд╣рд░ рдмрд╛рд░ canActivate
рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдзрд┐рдХреГрдд рд╣реИ, рддреЛ рд╡рд╣ /profile
рдкрде рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛, рдЕрдиреНрдпрдерд╛ рдЙрд╕реЗ /login
рдкрде рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдЖрдкрдХреЛ рдЗрд╕ рдмрд╛рдд рд╕реЗ рдЕрд╡рдЧрдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдЗрд╕ рдорд╛рд░реНрдЧ рдкрд░ рдЖрдк рдШрдЯрдХ рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдЗрд╕реЗ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред рдпрджрд┐ рдЖрдкрдХреЛ рдШрдЯрдХ рдХреА рд╕рдХреНрд░рд┐рдпрддрд╛ рдФрд░ рд▓реЛрдбрд┐рдВрдЧ рдХреА рд░рдХреНрд╖рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЗрд╕ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рд╣рдо canLoad
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред CanLoad
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕рд╛рджреГрд╢реНрдп рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдкрд╛рдХ рдХрд▓рд╛ RxJS
RxJS рдХреЗ рдКрдкрд░ рдХреЛрдгреАрдп рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред RxJS рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдФрд░ рдШрдЯрдирд╛-рдЖрдзрд╛рд░рд┐рдд рдбреЗрдЯрд╛ рдзрд╛рд░рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИ рдЬреЛ рдЕрд╡рд▓реЛрдХрди рдпреЛрдЧреНрдп рдЕрдиреБрдХреНрд░рдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред RxJS ReactiveX API рдХрд╛ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред рдЕрдзрд┐рдХрд╛рдВрд╢ рднрд╛рдЧ рдХреЗ рд▓рд┐рдП, рдЗрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рд╣реЛрдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдЗрд╕рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рдХреЗ рд╕рддрд╣реА рдЬреНрдЮрд╛рди рд╕реЗ рдЬреБрдбрд╝реА рд╣реИрдВред
рдИрд╡реЗрдВрдЯ рдХреЗ рд▓рд┐рдП рд╕рд╛рдЗрди рдЕрдк рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдПрд╕реНрдХреН рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЬреЛ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдХреЛрдгреАрдп рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдП рд╣реИрдВ, рдШрдЯрдХ рдореЗрдВ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рд╕рд╣реЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП Observable
рдХреА subscribe
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
@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; }); } }
рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдо 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"); } }
рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдиреЗ рд╕реЗ, рд╣рдо рдореЗрдореЛрд░реА рд▓реАрдХ рд╕реЗ рдмрдЪрддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдХреЛрдгреАрдп рдПрдХ рдШрдЯрдХ рдХреЗ рдЯреВрдЯрдиреЗ рдкрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ Observable
рд╕реЗ Observable
рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП, async рдкрд╛рдЗрдк рдХрд╛ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдХреЛрдИ рд▓рд╛рдн рдирд╣реАрдВ рдорд┐рд▓рддрд╛ рд╣реИ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ - async рдЕрдиреБрд░реЛрдз рдХреЛ рд░рджреНрдж рдХрд░ рджреЗрдЧрд╛ рдпрджрд┐ рдбреЗрдЯрд╛ рдХреА рдЕрдм рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдкреВрд░рд╛ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред
Observables
рдХреА рдХрдИ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдиреЗ рдХреЗ рджреМрд░рд╛рди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред Observables
рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рджреЛрд╣рд░рд╛рдХрд░ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, http рдЕрдиреБрд░реЛрдз рдореЗрдВ рдкреБрди: рдкреНрд░рдпрд╛рд╕), рдЯрд╛рдЗрдорд░-рдЖрдзрд╛рд░рд┐рдд рдЕрджреНрдпрддрди рдпрд╛ рдкреВрд░реНрд╡-рдХреИрд╢рд┐рдВрдЧ рджреНрд╡рд╛рд░рд╛ рдмрдврд╝рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рд╡реЗрдзрд╢рд╛рд▓рд╛рдУрдВ рдХреЛ рдирд┐рд░реВрдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП $
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдЕрдЧрд▓рд╛ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рдЖрд╡реЗрджрди рд╕реНрд░реЛрдд рдХреЛрдб рдХреЗ рдбрд┐рдЬрд╛рдЗрди рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИ рдФрд░ рдкрд┐рдЫрд▓реЗ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рд╕реЗ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИред Observable
рдХреЛ рд╕рд░рд▓ рдЪрд░ рд╕реЗ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдХреНрд╕рд░ рдЖрдк рдХрд┐рд╕реА рдЪрд░ рдпрд╛ рдХреНрд╖реЗрддреНрд░ рдХреЗ рдирд╛рдо рдкрд░ " $
" рдЪрд┐рдиреНрд╣ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рд▓рд╛рд╣ рд╕реБрди рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рд╕рд░рд▓ рдЪрд╛рд▓ 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(); } }
рдЬрдм рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░реЗрдВ (рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░реЗрдВ)
рд╕рдмрд╕реЗ рдЖрдо рд╕рд╡рд╛рд▓ рдЬреЛ рдПрдХ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рдкрд╛рд╕ рд╣реИ рдЬрдм рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдХреЛрдгреАрдп рдХреЛ рдкрддрд╛ рдЪрд▓ рд░рд╣рд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдЕрднреА рднреА рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдЬрдм рдирд╣реАрдВред рдЗрд╕ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рдпрд╣ рддрдп рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ Observable
рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рдХреЛрдгреАрдп рдореЗрдВ Observable
2 рдкреНрд░рдХрд╛рд░ рд╣реЛрддреЗ рд╣реИрдВ - рдкрд░рд┐рдорд┐рдд рдФрд░ рдЕрдирдВрдд, рдХреБрдЫ рдПрдХ рдкрд░рд┐рдорд┐рдд, рдЕрдиреНрдп, рдХреНрд░рдорд╢рдГ, рдореВрд▓реНрдпреЛрдВ рдХреА рдПрдХ рдЕрдирдВрдд рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░рддреЗ рд╣реИрдВред
Http
Observable
рдХреЙрдореНрдкреИрдХреНрдЯ рд╣реИ, рдФрд░ DOM рдЗрд╡реЗрдВрдЯ рдХреЗ рд╢реНрд░реЛрддрд╛ / рд╢реНрд░реЛрддрд╛ рдЕрдирдВрдд Observable
ред
рдпрджрд┐ рдПрдХ рдЕрдирдВрдд Observable
рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ (рдПрд╕рд┐рдВрдХреНрд╕ рдкрд╛рдЗрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛) рдХреА рдЬрд╛рддреА рд╣реИ, рддреЛ рдПрдХ рдЙрддреНрддрд░ рдмрд┐рдирд╛ рдЕрд╕рдлрд▓ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рд╣рдо рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдПрдХ рдкрд░рд┐рдорд┐рдд рдЕрд╡рд▓реЛрдХрди рдХреЗ рд▓рд┐рдП рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ, RxJS рдЗрд╕ рдмрд╛рдд рдХрд╛ рдзреНрдпрд╛рди рд░рдЦреЗрдЧрд╛ред рдХреЙрдореНрдкреИрдХреНрдЯ Observables
рдорд╛рдорд▓реЗ рдореЗрдВ Observables
рд╣рдо Observables
рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ Observable
рдкрд╛рд╕ рдЖрд╡рд╢реНрдпрдХ рдирд┐рд╖реНрдкрд╛рджрди рд╕реЗ рдЕрдзрд┐рдХ рд╕рдордп рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдорд▓реНрдЯреАрдкрд▓ HTTP рдЕрдиреБрд░реЛрдзред
рдХреЙрдореНрдкреИрдХреНрдЯ Observables
рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг:
export class SomeComponent { constructor(private http: HttpClient) { } ngOnInit() { Observable.timer(1000).subscribe(...); this.http.get("http://api.com").subscribe(...); } }
рдЕрдирдВрдд рд╡реЗрдзрд╢рд╛рд▓рд╛рдУрдВ рдХрд╛ рдЙрджрд╛рд╣рд░рдг
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(); } }
рдиреАрдЪреЗ, рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг рдореЗрдВ рд╡реЗ рдорд╛рдорд▓реЗ рд╣реИрдВ рдЬрд┐рдирдореЗрдВ рдЖрдкрдХреЛ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
- рдлреЙрд░реНрдо рд╕реЗ рдФрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдирд┐рдпрдВрддреНрд░рдгреЛрдВ рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рдЫреЛрдбрд╝рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдЙрдиреНрд╣реЛрдВрдиреЗ рд╕рджрд╕реНрдпрддрд╛ рд▓реА рдереА:
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(); } }
- рд░реВрдЯрд░ред рдкреНрд░рд▓реЗрдЦрди рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдХреЛрдгреАрдп рдХреЛ рдЕрдкрдиреЗ рдЖрдк рдХреЛ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ ред рдЗрд╕рд▓рд┐рдП, рдЖрдЧреЗ рдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЕрдкрдиреЗ рдЖрдк рд╕реЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
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() {
- рдЕрдВрддрд╣реАрди рдХреНрд░рдоред
interva()
рдпрд╛ рдЗрд╡реЗрдВрдЯ рд╢реНрд░реЛрддрд╛рдУрдВ (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 рдФрд░ takeWhile
RxJS рдореЗрдВ рдЕрдирдВрдд рд╡реЗрдзрд╢рд╛рд▓рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рджреЛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдХрд╛рд░реНрдп рд╣реИрдВ - takeUntil
рдФрд░ takeWhile
ред рд╡реЗ рдПрдХ рд╣реА рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ рд╣реИрдВ - рдХреБрдЫ рд╕реНрдерд┐рддрд┐ рдХреЗ рдЕрдВрдд рдореЗрдВ Observable
рд╕реЗ рдЕрдирд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд░рдирд╛, рдЕрдВрддрд░ рдХреЗрд╡рд▓ рд╕реНрд╡реАрдХреГрдд рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рд╣реИред takeWhile
рдПрдХ boolean
рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдФрд░ takeUntil
рдПрдХ Subject
takeUntil
рд╣реИред
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; } }
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЬрдм alive
рдзреНрд╡рдЬ рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ Observable
рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рдПрдЧреАред рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдШрдЯрдХ рдХреЗ рдирд╖реНрдЯ рд╣реЛрдиреЗ рдкрд░ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░реЗрдВред
takeUntil
рдЙрджрд╛рд╣рд░рдг:
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(); } }
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, Observable
рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Observable
рд╣рдо рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ subject
рдЕрдЧрд▓рд╛ рдорд╛рди рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдкреВрд░рд╛ рдХрд░рддрд╛ рд╣реИред
рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рд▓реАрдХ рд╕реЗ рдмрдЪрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдбреЗрдЯрд╛ рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдХрд┐рд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ? рдЗрд╕ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдкреНрд░рд╛рдердорд┐рдХрддрд╛рдУрдВ рдФрд░ рд╡рд░реНрддрдорд╛рди рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдХреЛрдгреАрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рд░рд╛рдЬреНрдп рдкреНрд░рдмрдВрдзрди, @ ngrx / store
рдХрд╛рдлреА рдмрд╛рд░, рдЬрдм рдЬрдЯрд┐рд▓ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рд░рд╛рдЬреНрдп рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдФрд░ рдЗрд╕рдХреЗ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рд╕рд╛рде рд╕рд╛рдордирд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред ReactJs рдврд╛рдВрдЪреЗ рдкрд░ рд╡рд┐рдХрд╕рд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдХрдИ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЛ рдЖрд╡реЗрджрди рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдФрд░ рдЗрд╕рдХреЗ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ - рдлреНрд▓рдХреНрд╕, рд░реЗрдбрдХреНрд╕, рд░реЗрдбрдХреНрд╕-рд╕рд╛рдЧрд╛, рдЖрджрд┐ред рдХреЛрдгреАрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП, рдПрдХ RxJS рдЖрдзрд╛рд░рд┐рдд рд░рд╛рдЬреНрдп рдХрдВрдЯреЗрдирд░ рд╣реИ рдЬреЛ Redux рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реИ - @ ngrx / storeред рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рдЙрдЪрд┐рдд рдкреНрд░рдмрдВрдзрди рдбреЗрд╡рд▓рдкрд░ рдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЖрдЧреЗ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд╕рд╛рде рдХрдИ рд╕рдорд╕реНрдпрд╛рдУрдВ рд╕реЗ рдмрдЪрд╛рдПрдЧрд╛ред
рдХреНрдпреЛрдВ Redux
Redux рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрдорд╛рдирд┐рдд рд░рд╛рдЬреНрдп рдХрдВрдЯреЗрдирд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЦреБрдж рдХреЛ рддреИрдирд╛рдд рдХрд░рддрд╛ рд╣реИред Redux рдлреНрд▓рдХреНрд╕ рдФрд░ рдПрд▓реНрдо рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реИред
Redux рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЕрдиреБрдХреНрд░рдо рджреНрд╡рд╛рд░рд╛ рдПрдХ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЕрд╡рд╕реНрдерд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрддрд╛ рд╣реИ, рдЬреЛ рдЬрдЯрд┐рд▓ рд╡реЗрдм рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
Redux рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдлреНрд░реЗрдорд╡рд░реНрдХ рд╕реЗ рд╕рдВрдмрджреНрдз рдирд╣реАрдВ рд╣реИ, рдФрд░ рд╣рд╛рд▓рд╛рдБрдХрд┐ рдпрд╣ React рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ Angular рдпрд╛ jQuery рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
Redux рдХреЗ рдореБрдЦреНрдп рдкрдж:
- рдЖрд╡реЗрджрди рдХреЗ рдкреВрд░реЗ рд░рд╛рдЬреНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рднрдВрдбрд╛рд░
- рдХреЗрд╡рд▓ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╛рдЬреНрдп
- рдкрд░рд┐рд╡рд░реНрддрди "рд╢реБрджреНрдз" рдХрд╛рд░реНрдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдЕрдзреАрди рд╣реИрдВ:
- рдиреЗрдЯрд╡рд░реНрдХ рдпрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдкрд░ рдмрд╛рд╣рд░реА рдХреЙрд▓ рди рдХрд░реЗрдВ;
- рдПрдХ рдорд╛рди рд▓реМрдЯрд╛рдпрд╛ рдЬреЛ рдХреЗрд╡рд▓ рдкрд╛рд░рд┐рдд рдорд╛рдкрджрдВрдбреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ;
- рддрд░реНрдХ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реИрдВ, рдЕрд░реНрдерд╛рддреН рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЙрдиреНрд╣реЗрдВ рдмрджрд▓рдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рд┐рдП;
- рд╕рдорд╛рди рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╢реБрджреНрдз рдХрд╛рд░реНрдп рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣рдореЗрд╢рд╛ рдПрдХ рд╣реА рдкрд░рд┐рдгрд╛рдо рджреЗрддрд╛ рд╣реИ;
рд░рд╛рдЬреНрдп рдкреНрд░рдмрдВрдзрди рд╕рдорд╛рд░реЛрд╣ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг:
// 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 рдЖрд╡реЗрджрди рдХреЗ рдореБрдЦреНрдп рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ StoreModule.provideStore(reducers)
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣рдо рдЗрд╕реЗ рдХреЛрдгреАрдп рдЗрдВрдЬреЗрдХреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз StoreModule.provideStore(reducers)
:
// 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 { }
рдЗрд╕рдХреЗ рдмрд╛рдж, Store
рд╕реЗрд╡рд╛ рдХреЛ рдЖрд╡рд╢реНрдпрдХ рдШрдЯрдХреЛрдВ рдФрд░ рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ рдкреЗрд╢ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред Store.select () рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ "рд╕реНрд▓рд╛рдЗрд╕" рд╕реНрдерд┐рддрд┐ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
// 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 / рд░реВрдЯрд░-рд╕реНрдЯреЛрд░
рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЖрд╡реЗрджрди рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдЖрд╡реЗрджрди рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЗрди рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП, @ ngrx / рд░реВрдЯрд░-рд╕реНрдЯреЛрд░ рдореЙрдбреНрдпреВрд▓ рдореМрдЬреВрдж рд╣реИред рд░рд╛рдЬреНрдп рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП router-store
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП, рдмрд╕ routerReducer
рдХрдиреЗрдХреНрдЯ routerReducer
рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдореБрдЦреНрдп рдореЙрдбреНрдпреВрд▓ рдореЗрдВ routerReducer
рдХреЙрд▓ рдЬреЛрдбрд╝реЗрдВ:
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 { }
рдЕрдм рдЖрд╡реЗрджрди рдХреЗ рдореБрдЦреНрдп рд░рд╛рдЬреНрдп рдореЗрдВ RouterState
рдЬреЛрдбрд╝реЗрдВ:
import { RouterState } from "@ngrx/router-store"; export interface AppState { ... router: RouterState; };
рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд, рд╣рдо рд╕реНрдЯреЛрд░ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╕рдордп рдЖрд╡реЗрджрди рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рдВрдХреЗрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
StoreModule.provideStore( { router: routerReducer }, { router: { path: window.location.pathname + window.location.search } } );
рд╕рдорд░реНрдерд┐рдд рдХрд╛рд░реНрдп:
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: рдЯрд┐рдкреНрдкрдгреА рдиреЗ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ рдХрд┐ рдпреЗ рдХреНрд░рд┐рдпрд╛рдПрдВ рдирдП рд╕рдВрд╕реНрдХрд░рдг @ngrx, рдирдП рд╕рдВрд╕реНрдХрд░рдг https://github.com/ngrx/platform/blob/master/MIGRATION.md#ngrxrouter-store рдкрд░ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реЛрдВрдЧреА
рдЬрдЯрд┐рд▓ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп рд░рд╛рдЬреНрдп рдХрдВрдЯреЗрдирд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдИ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░реЗрдЧрд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд░рд╛рдЬреНрдп рдкреНрд░рдмрдВрдзрди рдХреЛ рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рдмрдирд╛рдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдЕрдХреНрд╕рд░, рдПрдХ рдХреЛ рдЙрди рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рд╕реЗ рдирд┐рдкрдЯрдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд░рд╛рдЬреНрдпреЛрдВ рдХрд╛ рдЕрддреНрдпрдзрд┐рдХ рдШреЛрдВрд╕рд▓рд╛ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдХреЗрд╡рд▓ рдЖрд╡реЗрджрди рдХреА рд╕рдордЭ рдХреЛ рдЬрдЯрд┐рд▓ рдХрд░рддрд╛ рд╣реИред
рдХреЛрдб рд╕рдВрдЧрдарди
import
рдореЗрдВ рднрд╛рд░реА рднрд╛рд╡реЛрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдирд╛
рдХрдИ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдПрдХ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рд╕реЗ рдЕрд╡рдЧрдд рд╣реИрдВ, рдЬрд╣рд╛рдВ import
рдореЗрдВ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпрд╛рдБ рдмреЛрдЭрд┐рд▓ рд╣реИрдВред рдпрд╣ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдмрдбрд╝реЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдЬрд╣рд╛рдВ рдХрдИ рдкреБрди: рдкреНрд░рдпреЛрдЬреНрдп рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИрдВред
import { SomeService } from "../../../core/subpackage1/subpackage2/some.service";
рдЗрд╕ рдХреЛрдб рдореЗрдВ рдФрд░ рдХреНрдпрд╛ рдмреБрд░рд╛ рд╣реИ? рдпрджрд┐ рдЖрдкрдХреЛ рд╣рдорд╛рд░реЗ рдШрдЯрдХ рдХреЛ рдХрд┐рд╕реА рдЕрдиреНрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ import
рдореЗрдВ рджрд┐рдП рдЧрдП рднрд╛рд╡ рдорд╛рдиреНрдп рдирд╣реАрдВ рд╣реЛрдВрдЧреЗред
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЙрдкрдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рд╣рдо import
рдореЗрдВ рднрд╛рд░реА рднрд╛рд╡реЛрдВ рд╕реЗ рджреВрд░ рд╣реЛ рд╕рдХрддреЗ import
рдФрд░ рд╣рдорд╛рд░реЗ рдХреЛрдб рдХреЛ рдЕрдзрд┐рдХ рд╕реНрд╡рдЪреНрдЫ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЙрдкрдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ tsconfig.json рдореЗрдВ baseUrl рдФрд░ рдкрде рдЧреБрдг tsconfig.json
:
/ tsconfig.json { "compilerOptions": { ... "baseUrl": "src", "paths": { "@app/*": ["app/*"], "@env/*": ["environments/*"] } } }
рдЗрди рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд╕рд╛рде, рдкреНрд▓рдЧ-рдЗрди рдХреЛ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░рдирд╛ рдХрд╛рдлреА рдЖрд╕рд╛рди рд╣реИ:
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 ) { } }
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, SomeService
рд╕реАрдзреЗ SomeService
рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдмрдЬрд╛рдп @app/core
рд╕реЗ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЙрджрд╛ред @app/core/some-package/some.service
)ред рдореБрдЦреНрдп index.ts
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдШрдЯрдХреЛрдВ рдХреЗ рдкреБрди: рдирд┐рд░реНрдпрд╛рдд рдХреЗ рд▓рд┐рдП рдпрд╣ рд╕рдВрднрд╡ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдкреИрдХреЗрдЬ рдХреЗ рд▓рд┐рдП рдПрдХ index.ts
рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреА рдЬрд╛рддреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЖрдкрдХреЛ рд╕рднреА рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдореЙрдбреНрдпреВрд▓ рдХреЛ рдлрд┐рд░ рд╕реЗ рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ:
// index.ts export * from "./core.module"; export * from "./auth/auth.service"; export * from "./user/user.service"; export * from "./some-service/some.service";
рдХреЛрд░, рд╕рд╛рдЭрд╛, рдФрд░ рдлрд╝реАрдЪрд░ рдореЙрдбреНрдпреВрд▓
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдШрдЯрдХреЛрдВ рдХреЗ рдЕрдзрд┐рдХ рд▓рдЪреАрд▓реЗ рдкреНрд░рдмрдВрдзрди рдХреЗ рд▓рд┐рдП, рд╕рд╛рд╣рд┐рддреНрдп рдореЗрдВ рдФрд░ рдЗрд╕рдХреЗ рдШрдЯрдХреЛрдВ рдХреА рджреГрд╢реНрдпрддрд╛ рдХреЛ рдлреИрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рдЗрдВрдЯрд░рдиреЗрдЯ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдореЗрдВ рдЗрд╕рдХреА рдЕрдХреНрд╕рд░ рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЬрд╛рддреА рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрд╡реЗрджрди рдХреЗ рдШрдЯрдХреЛрдВ рдХрд╛ рдкреНрд░рдмрдВрдзрди рд╕рд░рд▓ рд╣реИред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬреБрджрд╛рдИ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдХреЛрд░, рд╕рд╛рдЭрд╛ рдФрд░ рдлрд╝реАрдЪрд░ рдореЙрдбреНрдпреВрд▓ред
CoreModule
CoreModule рдХрд╛ рдореБрдЦреНрдп рдЙрджреНрджреЗрд╢реНрдп рдЙрди рд╕реЗрд╡рд╛рдУрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╣реИ рдЬрд┐рдирдХреЗ рдкрд╛рд╕ рдкреВрд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реЛрдЧрд╛ (рдпрд╛рдиреА, рдПрдХрд▓ рдкреИрдЯрд░реНрди рд▓рд╛рдЧреВ рдХрд░реЗрдВ)ред рдЗрдирдореЗрдВ рдЕрдХреНрд╕рд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕реЗрд╡рд╛ рдпрд╛ рдПрдХ рд╕реЗрд╡рд╛ рд╢рд╛рдорд┐рд▓ рд╣реЛрддреА рд╣реИред 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 { constructor( @Optional() @SkipSelf() parentModule: CoreModule ) { if (parentModule) { throw new Error("CoreModule is already loaded. Import only in AppModule"); } } }
SharedModule
рдпрд╣ рдореЙрдбреНрдпреВрд▓ рд╕рд░рд▓ рдШрдЯрдХреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИред рдпреЗ рдШрдЯрдХ рдЕрдкрдиреЗ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдЕрдиреНрдп рдореЙрдбреНрдпреВрд▓ рд╕реЗ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдЖрдпрд╛рдд рдпрд╛ рдЗрдВрдЬреЗрдХреНрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдЙрдиреНрд╣реЗрдВ рдШрдЯрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рднреА рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред SharedModule
рдХрд╛ рд╣рдорд╛рд░реЗ рдмрд╛рдХреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд░ рдХреЛрдИ рдирд┐рд░реНрднрд░рддрд╛ рдирд╣реАрдВ рд╣реИред рдпрд╣ рдХреЛрдгреАрдп рд╕рд╛рдордЧреНрд░реА рдХреЗ рдШрдЯрдХреЛрдВ рдпрд╛ рдЕрдиреНрдп UI рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рдЖрдпрд╛рдд рдФрд░ рдкреБрдирдГ рдирд┐рд░реНрдпрд╛рдд рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрджрд░реНрд╢ рд╕реНрдерд╛рди рд╣реИред
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: [ CommonModule, FormsModule, MdButtonModule, SomeCustomComponent ] }) export class SharedModule { }
FeatureModule
рдпрд╣рд╛рдВ рдЖрдк рдХреЛрдгреАрдп рд╢реИрд▓реА рдЧрд╛рдЗрдб рдХреЛ рджреЛрд╣рд░рд╛ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд░рддреНрдпреЗрдХ рд╕реНрд╡рддрдВрддреНрд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ FeatureModule рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред FeatureModule рдХреЛ рдХреЗрд╡рд▓ CoreModule
рд╕реЗ рд╕реЗрд╡рд╛рдПрдБ рдЖрдпрд╛рдд рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рдХреБрдЫ рдореЙрдбреНрдпреВрд▓ рдХреЛ рдХрд┐рд╕реА рдЕрдиреНрдп рдореЙрдбреНрдпреВрд▓ рд╕реЗ рд╕реЗрд╡рд╛ рдЖрдпрд╛рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдЗрд╕ рд╕реЗрд╡рд╛ рдХреЛ CoreModule
рд▓реЗ рдЬрд╛рдпрд╛ CoreModule
ред
рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдХреЗрд╡рд▓ рдХреБрдЫ рдореЙрдбреНрдпреВрд▓ рджреНрд╡рд╛рд░рд╛ рд╕реЗрд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ CoreModule
рдХреЛ рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдк рдПрдХ рд╡рд┐рд╢реЗрд╖ SharedModule
рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рдЗрди рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
, тАФ , - , , CoreModule
, SharedModule
.
, . , . , , .
рд╕рдВрджрд░реНрдн
- https://github.com/ngrx/store
- http://stepansuvorov.com/blog/2017/06/angular-rxjs-unsubscribe-or-not-unsubscribe/
- https://medium.com/@tomastrajan/6-best-practices-pro-tips-for-angular-cli-better-developer-experience-7b328bc9db81
- https://habr.com/post/336280/
- https://angular.io/docs