The playground

More information here

Smoother UX pe pagina de încărcare cu resolvers unghiulare

ca un dezvoltator, sunteți mereu în căutarea pentru a optimiza codul. Aceasta include viteza cu care prezentați utilizatorului UI complet încărcat, care depinde adesea de datele provenite dintr-o bază de date. inevitabil, începeți să căutați modalități de rezolvare a datelor imediat după navigarea către o nouă pagină / zonă a aplicației dvs., fără ca utilizatorul […]

ca un dezvoltator, sunteți mereu în căutarea pentru a optimiza codul. Aceasta include viteza cu care prezentați utilizatorului UI complet încărcat, care depinde adesea de datele provenite dintr-o bază de date.

inevitabil, începeți să căutați modalități de rezolvare a datelor imediat după navigarea către o nouă pagină / zonă a aplicației dvs., fără ca utilizatorul să întâlnească ceea ce este cunoscut sub numele de page JANK.

aceasta este atunci când pagina se mișcă în sus și în jos în timp ce se încarcă anumite componente. Aceasta poate afecta în mod semnificativ UX până la punctul în care se pare ‘buggy’.

Angular oferă o abordare intuitivă a pre-preluarea datelor înainte de încărcarea traseului; înainte ca ruta navigată să se rezolve.

se numește un rezolvator unghiular.

un Resolver unghiular este în esență un serviciu unghiular. O clasă injectabilă pe care o furnizați unui modul de rutare în configurația traseului. Acest tip special de serviciu este injectat și executat atunci când ruta care conține este navigată.

resolverul rezolvă apoi datele înainte de încărcarea paginii, care devine disponibilă prin serviciulActivatedRoute. Aceasta oferă o modalitate simplă și eficientă de a vă asigura că utilizatorul dvs. are datele cât mai repede posibil înainte ca o componentă importantă pentru încărcarea inițială a paginii să aibă nevoie de ea.

Un alt mod de a utiliza un Resolver unghiular este folosind-o ca metodă de a popula metadatele SEO instantaneu.

cu un resolver, oferiți o garanție că datele vor exista înainte de încărcarea paginii, asigurându-vă că totul are ceea ce are nevoie la inițializare.

să defalcare resolver unghiular

un resolver unghiular este o clasă care implementează Resolve interfață. InterfațaResolve necesită implementarea unei funcții în clasa numităresolve.

aici este semnătura interfeței de rezolvare…

export interface Resolve<T> {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T> | Promise<T> | T {
return 'data';
}
}

după cum putem vedea din semnătura interfeței, este nevoie de un argument genericT care va fi tipul datelor noastre rezolvate.

funcția resolve returnează un ObservablePromise sau doar datele de tip T . Prin urmare, există o sugestie că acest lucru ar trebui să fie tratate asincron, mai ales dacă regăsirea datelor din Baza de date.

scopul principal al funcției resolve este că trebuie să se finalizeze. Acest fapt trebuie amintit atunci când se recuperează date în observabile. Observabilul trebuie completat. La urma urmei, este un rezolvator.

dacă observabilul nu se finalizează, atunci datele nu se vor rezolva niciodată și pagina nu se va încărca niciodată. Prin urmare, trebuie să definiți punctul în care nu trebuie să mai luați valori și datele se pot rezolva, deoarece aveți tot ce aveți nevoie din Baza de date. Atunci când se utilizează fluxuri de date asincrone, cum ar fi observabile, acesta este un caz de utilizare pentru operatorii de conducte de la RXJS.

operatorii pipeable care primăvară în minte atunci când gândesc la completarea unui flux de date bazate pe o condiție, este o combinație defiltertakefirst . Cu această combinație, puteți filtra toate valorile pe care nu doriți să le luați, cum ar fi null sau undefined sau o matrice goală , apoi take prima valoare validă cu take(1).

operatorii care pot fi necesari pentru a finaliza o observație timpurie atunci când întâmpinați probleme sau erori, în care veți dori să returnați null sau redirecționați, suntcatchError șitimeout . O combinație de timeout și catchError este utilă dacă datele dvs. durează prea mult și doriți să returnați null astfel încât să puteți încerca din nou în interiorul componentei sau doriți să redirecționați.

dacă datele dvs. nu se rezolvă rapid, se bazează pe Filtrare complexă, logică, cantități uriașe de apeluri de baze de date, este posibil să întâmpinați probleme din când în când.

cel mai bine este să determinați cea mai mică cantitate de apeluri de baze de date și datele minime necesare pentru a încărca cu succes și grațios pagina.

în consecință, este posibil să beneficiați de ceva timp, înainte de a implementa resolverul, pentru a vă concentra pe separarea conținutului ‘above the fold’ de datele care pot fi încărcate atunci când pagina se inițializează.

prin urmare, puteți împărți datele necesare pentru un UX neted, din restul datelor care ar putea fi apelate din componentă, mai degrabă decât din rezolvator.

Puteți apoi să vă ocupați exclusiv de conținutul minim, deasupra pliului, prin intermediul rezolvatorului.

această abordare dinamică a încărcării paginilor poate fi asistată cu utilizarea scheletelor. Astfel încât, dacă utilizatorul derulează instantaneu, puteți oferi utilizatorului indicația că conținutul se încarcă, îmbunătățind ulterior UX.

Pasul 1: Crearea Resolver

avem nevoie pentru a crea Resolver unghiular. Cu toate acestea, nu există o comandă CLI unghiulară care generează un rezolvator. Prin urmare, va trebui să scriem noi înșine Decoratorul (resolver metadata).

Din fericire, este doar câteva linii de cod care formează cazanul pentru un rezolvator, și putem lua decorator injectabil de la un serviciu existent, dacă sunteți luptă să-l amintesc.

Adnotați clasa de rezolvare a profilului cu un decorator injectabil

În primul rând, oferim decoratorului injectabilprovidedIn: any în configurație.

@Injectable({ providedIn: 'any'})

vom numi apoi rezolvatorul nostru prin adăugarea Convenției Resolver . Pentru acest exemplu, vom rezolva datele de profil (datele utilizatorului), așa că le vom numi ProfileResolver .

deoarece este un rezolvator și Angular recunoaște funcția rezolvatorilor, putem implementaResolve clasă, care va furniza semnătura pe care trebuie să o implementăm în funcția noastră de rezolvare pentru a rezolva cu succes datele.

@Injectable({providedIn: 'any'})
export class ProfileResolver implements Resolve<Profile> {
}

funcția noastră de rezolvare va returna un observabil cu date conforme cuProfile interfață. Prin urmare, vom furniza interfața Profile ca argument generic pentru clasa de rezolvare și funcția resolve(). În acest fel ne-am conformat cerințelor unghiulare pentru un rezolvator.

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T> | Promise<T> | T {
return;
}

implementarea rezolvării ne oferă doi parametri dacă sunt necesari,route șistate . Acestea sunt populate automat și sunt accesibile din cadrul funcției noastre resolve().

în continuare, trebuie să rezolvăm efectiv datele reale din Baza de date, care va fi următorul nostru pas.

preluarea datelor din Baza de date

pentru a prelua datele pentru funcția noastră de rezolvare, va trebui să injectăm serviciul care furnizează datele; unul care interacționează cu baza de date.

luăm ceea ce avem nevoie de la ea pentru a rezolva rapid, astfel încât utilizatorul să navigheze prompt și cu succes. În scopul acestui demo, nu ne vom face griji cu privire la serviciul de bază care se ocupă de baza de date. Vom injecta doar serviciul folosind injecția de dependență în Argumentul constructor pentru ProfileResolver clasă.

deoarece datele noastre vin sub forma unui flux de date observabil cu valori multiple care emit asincron, va trebui doar sătake(1) folosind operatorul pipeabletake importat dinrxjs/operator . În caz contrar, observabilul nu s-ar finaliza niciodată, iar rezolvatorul nu s-ar rezolva niciodată.

avem nevoie doar de o emisie/valoare șitake completează observabilul pentru noi.

este la fel de simplu ca acela de a crea un rezolvator; trebuie doar să returnăm observabilul înresolve() funcția pe care angular o va gestiona abonamentul.

clasa ProfileResolver

gestionăm orice erori în preluarea datelor prin redirecționarea către un traseu părinte.

Bonus: Populați metadatele SEO dinamice rapid înainte ca ruta să se încarce

beneficiile populării etichetelor noastre<meta> au instantaneu beneficii evidente. Cu cât metadatele noastre SEO sunt populate mai repede, cu atât SEO-ul nostru reflectă corect și corect conținutul paginii.aceasta înseamnă că este mai ușor și mai rapid pentru roboți, cum ar fi cei operați de motoarele de căutare precum Google și Bing, să acceseze cu crawlere site-ul dvs. și să recupereze conținutul.

Acest lucru nu este atât de important pe paginile pre-randate sau pe cele care sunt randate de Angular Universal, deoarece toată redarea este completă înainte ca roboții să primească conținutul.

cu toate acestea, dacă vă bazați pe capacitatea (adesea discutabilă) a roboților google de a analiza javascript pentru SEO-ul dvs. sau dacă aveți o soluție la cerere, cum ar fi păpușarul, care are nevoie de asigurarea că SEO va fi corect înainte de a returna DOM-ul redat, atunci un rezolvator care include SEO ar trebui să vă ajute. Deci, ajută atunci când crawlerul este limitat în timp.

de asemenea, separă preocupările de componentă, astfel încât componenta nu trebuie să se ocupe de nimic legat de SEO. Unul dintre principalele motive pentru care îmi plac rezolvatorii.

Pasul 2: injectați resolverul în modulul de rutare

ProfileRoutingModule unde vom furniza resolverul nostru este un modul încărcat leneș. Prin urmare , calea noastră rădăcină va fi goală cu parametrul token userSlug, de care va trebui să recuperăm datele corecte ale profilului.

pentru a furniza rezolvatorul nostru, furnizăm doar un obiect cu numele datelor noastre ca cheie și rezolvatorul specific ca valoare care va fi responsabilă pentru rezolvarea acestor date.

puteți numi cheia orice doriți, dar o vom numi doar date.

ProfileRoutingModule nostru

asta e tot ceea ce este necesar în modulul de rutare pentru noi de a utiliza resolver nostru.

apoi, avem nevoie pentru a prelua și de a folosi datele noastre în componenta.

Pasul 3: Inițializați componenta cu date rezolvate

acum că am rezolvat datele noastre privind activarea rutei, datele sunt accesibile prin serviciulActivatedRoute. Pe măsură ce avem de-a face cu observabile, pe tot parcursul aplicației, vom crea un flux care se leagă de data proprietate care va fi datele noastre rezolvate.

În primul rând, vom injectaActivatedRoute în constructorulProfileComponent . Apoi, vom atribuithis.route.dataprofile$ observabil. De asemenea, vom dori să trecem la utilizarea unui observabil atunci când datele actualizate sosesc din Baza de date, astfel încât să avem date noi atunci când interacționăm cu aplicația.

pentru aceasta, vom folosi startWith pentru a începe fluxul nostru cu valoarea care este ușor accesibilă de la this.route.snapshot.data. Apoi accesăm data proprietate precum this.route.snapshot.datastartWith indică o valoare cu care să începem, ca prima emisie a fluxului nostru.

componenta noastră de profil

ce fac datele accesibile imediat pentru componenta

datele accesibile imediat reduc timpul petrecut încărcând părțile individuale ale acelei pagini, care este observat de utilizator. Rezultatul nefolosirii unui rezolvator ca acesta este că pagina poate părea să se încarce într-un mod fragmentat, ceea ce nu este plăcut vizual.

în consecință, va trebui să acordați atenție elementelor șabloanelor HTML care depind de ce date. Apoi, ar trebui să scrieți rezolvatorul dvs. pentru a susține aceste elemente și efectul general asupra încărcării paginii UX.

există mai multe moduri în care componenta poate încărca fragmentat

  • una dintre acestea este dacă aveți unngIf în mai multe părți ale șablonului HTML.
  • altul estengFor .

este cea mai bună practică pentru a limita cantitatea de individngIf pe care o scrieți în scopul limitării cantității de redimensionare a browserului.

încărcarea paginii înainte de a obține datele poate provoca părți ale paginii dvs. să sară, să întârzie și să redimensioneze constant, provocând UX-ul să sufere.

implementarea unui rezolvator ar putea fi diferența dintre utilizatorul care se confruntă cu 3-5 secunde de sărituri și redimensionare față de 0,5 secunde, ceea ce este adesea prea rapid pentru a fi dăunător UX-ului general.

asta e! Avem un rezolvator cu un UX îmbunătățit la încărcarea paginii.

Lasă un răspuns

Adresa ta de email nu va fi publicată.