Angular Route se rezolvă în 10 minute

Update on 07/13/2018: Revizuirea extensivă a codului pentru a utiliza convenții mai noi. Am actualizat Angular și RxJS la cele mai recente versiuni disponibile, am mutat exemplele la StackBlitz.

Obiectivul acestei postări este de a demonstra cum funcționează rezolvările de rute Angular în 10 minute, împreună cu furnizarea de exemple de cod pe Stackblitz. Dacă sunteți deja familiarizați cu route resolves din AngularJS, vă recomand să săriți peste introducere și să treceți direct la secțiunea de exemple de aplicații.

Carte de materii

Intro
Aplicație de exemplu

  • Pasul 1: Creați o clasă Resolver
  • Pasul 2: Adăugați un Resolve Guard la Route
  • Pasul 3: Adăugați un Resolve Guard la Route
  • Pasul 3: Adăugați un Resolve Guard la Route
  • : Obțineți datele rezolvate din ruta activată a componentei

Note & Sfaturi

  • Evitarea apelurilor API redundante
  • Rezolvarea multiplă pe aceeași rută
  • Passing Route Params to the Resolver

Note de închidere

Intro

Route resolves are nothing more than a way to pre-a prelua datele de care o componentă are nevoie înainte de a fi inițializată. De obicei, aceste date provin de la o API. Să presupunem că aveți o componentă al cărei unic rol este de a afișa un grafic al vânzărilor zilnice pentru luna respectivă; Nu are rost să redați vizualizarea sau să încărcați această componentă înainte ca datele de vânzări să fie disponibile. De fapt, multe biblioteci de creare a graficelor vor arunca o eroare dacă încercați să inițializați un grafic înainte de a-i furniza datele (la fel și *ngFor). Desigur, puteți ocoli cu ușurință această problemă ascunzând html-ul cu un *ngIf sau furnizând temporar o matrice goală până când datele necesare sunt încărcate. Cu toate acestea, deși vă puteți descurca și fără rezolvări, implementarea lor ajută la o mai bună lizibilitate și întreținere a codului prin:

  1. Eliminarea dezordinii confuze din șablonul și codul componentei dvs.
  2. Clarificându-vă intenția, arătând ce date trebuie preîncărcate.

În ciuda acestor beneficii, multe site-uri evită să utilizeze rezolvări în favoarea afișării celei mai mari părți a componentei și a afișării unui spinner în secțiunile pentru care datele sunt încă în curs de încărcare. În unele cazuri, această abordare este de dorit din punct de vedere UX, iar un resolve nu ar trebui să fie utilizat. Folosiți discreția dumneavoastră.

Sample App

Open Sample App

După cum puteți vedea, punctul nostru de plecare este o aplicație foarte simplă, cu două rute – „Home” și „News”. Se navighează între rute făcând clic pe fila corespunzătoare. Vom adăuga o rezolvare pentru a prelua știri de la o API înainte de încărcarea componentei News. Acest lucru se va face în trei pași:

Pasul 1: Creați o clasă de rezolvare care face un apel Http pentru a prelua în prealabil datele de care avem nevoie.

Creați un nou fișier Typescript în interiorul folderului app și numiți-l:

news-resolver.service.ts

Apoi copiați și lipiți următorul cod în noul fișier (explicat mai jos):

Să despărțim ce am făcut în codul de mai sus:

  • Aducem declarații de import ES6 pentru a aduce modulele necesare.

  • Am creat o nouă clasă TypeScript NewsResolver.

  • Am adăugat interfața Resolve la clasa noastră – aceasta este OPȚIONALĂ, dar orice clasă pe care plănuim să o folosim ca rezolvator trebuie să implementeze o metodă de rezolvare, deci este o convenție bună.

  • Am adăugat o metodă resolve() la NewsResolver – aceasta este metoda responsabilă pentru returnarea datelor de care avem nevoie. Numirea metodei care returnează datele pentru o gardă de rezolvare „resolve” NU este opțională – rezolvatorul nu ar funcționa dacă metoda s-ar numi altfel.

  • Dacă ați observat că în codul de mai sus se folosește în mod incorect o cerere POST în loc de o cerere GET, aveți perfectă dreptate; Într-o aplicație reală, aceasta ar fi o cerere GET. Exemplele de aici profită de , care este un site care oferă puncte finale API de testare.

Înainte de a trece mai departe, trebuie să includem clasa resolver pe care tocmai am creat-o în modulul nostru de rutare. Navigați la app-routing.module.ts și adăugați NewsResolver la matricea providers. Sau, dacă abia începeți să lucrați cu Angular 2, înlocuiți pur și simplu conținutul din app-routing.module.ts cu codul de mai jos – modificările sunt marcate cu note:

După ce am făcut acest lucru, am definit acum clasa resolver. În următorii pași, o vom adăuga la traseul nostru.

Cod după adăugarea clasei Resolver

Pasul 2: Adăugați un Resolve Guard la traseu.

În app-routing.module.ts, schimbați următoarea linie de cod { path: 'news', component: NewsComponent } în:

{ path: 'news', component: NewsComponent, resolve: { news: NewsResolver }}

Tot ce am făcut aici a fost să adăugăm resolve guard-ul pe care tocmai l-am definit la traseul nostru news. Acest lucru îi spune lui Angular că trebuie să așteptăm ca metoda resolve() a lui NewsResolver să returneze date înainte de a afișa NewsComponent.

Este important să subliniem că news din linia news: NewsResolver de cod este ceea ce am ales să numesc orice date returnate de către rezolvator. Puteți să-i dați orice nume doriți.

Ca o mică notă tangențială – dacă nu sunteți familiarizați cu gardienii de traseu Angular în general și doriți să aflați mai multe, documentația este aici. Intrarea în detalii despre gardieni este în afara scopului acestei postări, dar ar trebui să știți că există și alți gardieni în afară de resolve disponibili, motiv pentru care am adus în discuție acest termen.

Cod cu gardianul Resolve adăugat

Pasul 3: Obțineți datele rezolvate din ruta activată a componentei.

Acum că avem o clasă de rezolvare și am adăugat-o la ruta noastră, datele sunt preluate în prealabil. Ultimul pas este să accesăm datele pre-fetchate în NewsComponent al nostru situat în app/news.component.ts. Navigați în acel fișier și adăugați următorul modul ES6:

import { ActivatedRoute } from '@angular/router';

apoi furnizați ActivatedRoute în constructorul componentei News prin adăugarea următorului cod în partea de sus a definiției clasei NewsComponent:

constructor(private route: ActivatedRoute) {}

După cum știți, sau poate ați ghicit, ActivatedRoute ne permite să accesăm informații despre ruta care este activă în acel moment, cum ar fi url-ul rutei, parametrii de interogare etc. Ceea ce ne interesează aici sunt datele de știri care se încarcă în ActivatedRoute din garda de rezolvare. Pentru a obține datele de știri rezolvate din traseu, adăugați o proprietate care să dețină datele de știri:

public news: any;

și apoi obțineți datele din traseul activat atunci când NewsComponent este inițializat:

 ngOnInit(): void { this.news = this.route.snapshot.data; }

Acesta este practic tot. Schimbați șablonul componentei de știri pentru a afișa știrile din rezolvarea traseului, eliminând conținutul actual:

<div>This is just a placeholder for now. News will go here. </div>

și înlocuindu-l cu:

Ar trebui acum să fiți întâmpinați cu cea mai recentă știre, „Cerul este albastru”, atunci când faceți clic pe fila Știri.

Cod finalizat

Note & Sfaturi

– Rezolvările pot cauza apeluri API redundante: O rezolvare obține date de fiecare dată când o componentă este încărcată. Acest lucru duce adesea la apeluri API inutile care afectează negativ performanța. Dacă rezolvarea dvs. obține date care nu se schimbă frecvent, luați în considerare scrierea datelor returnate de rezolvare într-o proprietate din clasa de rezolvare și returnarea simplă a acelei proprietăți dacă aceasta a fost deja setată. De exemplu, în exemplul nostru, am adăuga o proprietate news inițial nedefinită, după cum urmează: public news: any = undefined; în rezolutorul nostru de știri. Apoi, în metoda resolve(), să verificăm dacă proprietatea news este deja setată și să returnăm valoarea acesteia fără a efectua un apel API dacă este, adică:

 resolve(): Observable<any> { if (this.news) { return this.getSavedNews(); } else { return this.getNewsFromApi() } }

Exemplu de cod complet mai jos. Dacă sintaxa observabilă vi se pare puțin neobișnuită, este pentru că eu folosesc RxJS 6. Există un tutorial bun despre modificările introduse recent în RxJS aici, dacă aveți nevoie de o reîmprospătare.

Return Saved Data, if Already Fetched from API

Natural, ați putea merge mai departe și să stabiliți o perioadă de timp în care datele sunt valabile, nu doar salvând datele, ci adăugând o altă proprietate timestamp și efectuând un apel API dacă datele sunt mai vechi de x.

– La fel ca în AngularJS, puteți utiliza mai multe rezolvări pe aceeași rută. Apelurile de rezolvare sunt efectuate în paralel, iar componenta se va încărca numai după ce toate apelurile returnează date. Pentru a utiliza mai multe rezolvări, este suficient să le adăugați la rută:

Apoi datele suplimentare de rezolvare pot fi accesate din instantaneul de rută, la fel ca o singură rezolvare:

 ngOnInit(): void { this.news = this.route.snapshot.data; this.alternativeNews = this.route.snapshot.data; }

Cod cu rezolvări multiple

– Rezolvatorul are acces la parametrii de rută. Să spunem că aveți o componentă care afișează o listă de titluri de știri. Atunci când se face clic pe o știre, se deschide o altă componentă, care afișează articolul complet. Înainte de a încărca acea componentă, trebuie să preluăm în prealabil conținutul articolului de știri al cărui titlu a fost apăsat – acest lucru se poate face în metoda resolve. Clasa de rezolvare are acces la ActivatedRoute, astfel încât putem obține id-ul articolului pe care s-a făcut clic:

 resolve(route: ActivatedRouteSnapshot) { let id: any = route.params); return this.getNewsStory(id); }

Acest lucru este destul de simplu de explicat. Pentru un exemplu, consultați noul fișier src/news-story-resolver.service.ts din link-ul de mai jos. Legăturile către noua componentă au fost adăugate în fila News (news.component.ts).

Cod cu rezolvare parametrizată

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.