Implementarea ecranelor schelet în React

Publicat: 2022-03-10
Rezumat rapid ↬ În acest tutorial, veți afla ce este o interfață de utilizare a ecranului schelet și câteva tipuri de biblioteci de ecran schelet, împreună cu avantajele și dezavantajele acestora. Vom construi o interfață de utilizare a ecranului schelet asemănătoare YouTube folosind React Loading Skeleton. Apoi, puteți experimenta pe cont propriu cu pachetul React de ecran schelet la alegere.

Spinnerele și încărcătoarele au fost în mod tradițional modalitatea de a le spune utilizatorilor că conținutul va dura ceva timp pentru a se încărca. Deși această abordare este grozavă, devine rapid învechită în dezvoltarea modernă. Ecranele de tip schelet devin înlocuitorul perfect pentru încărcătoarele tradiționale, deoarece se concentrează mai degrabă pe progres decât pe timpii de așteptare, reducând astfel frustrarea în timpul încărcării.

În acest articol, nu vom trece prin elementele de bază ale CSS React sau sintaxei JavaScript, așa că nu trebuie să fii un expert în niciuna dintre aceste limbi pentru a urma.

Diferența dintre un încărcător și o interfață de utilizare a ecranului schelet
Diferența dintre un încărcător și o interfață de utilizare a ecranului schelet (previzualizare mare)

Experții UI și UX ne învață că, în timp ce utilizatorii așteaptă ca conținutul să se încarce pe o pagină, ar trebui să-i menținem implicați.

Ideea din spatele utilizării filatoarelor pentru a implica utilizatorii înainte de încărcarea conținutului este grozavă; cu toate acestea, rezultatul poate fi mai puțin decât ideal, deoarece majoritatea utilizatorilor se vor plictisi privind la un rotor animat fals ca și cum ar fi un ceas. Luke Wroblewski detaliază acest lucru.

Ecranele schelet oferă o experiență mai bună pentru utilizator, reducând frustrarea în timpul încărcării. Concentrându-se pe progres în loc de timpii de așteptare, se creează iluzia utilizatorilor că informațiile vor fi afișate progresiv pe ecran. Bill Chung în cercetările sale confirmă acest lucru.

Ce este un ecran schelet?

Un ecran schelet este o versiune a interfeței de utilizare care nu conține conținut real; în schimb, imită aspectul paginii, arătând elementele acesteia într-o formă similară cu conținutul real, pe măsură ce se încarcă și devine disponibil (adică atunci când latența rețelei permite).

Un ecran schelet este în esență un cadru fir al paginii, cu casete de substituent pentru text și imagini.

Mai multe după săritură! Continuați să citiți mai jos ↓

Ce este unic la un ecran schelet?

O interfață de utilizare schelet seamănă cu interfața de utilizare reală a paginii, astfel încât utilizatorii vor înțelege cât de repede se va încărca aplicația web sau mobilă chiar înainte ca conținutul să apară. Iată câteva motive pentru care ați putea dori să luați în considerare utilizarea ecranelor schelet în următorul dvs. proiect:

  • imitarea aspectului unei pagini este mai ușoară cu un ecran schelet,
  • continutul se incarca progresiv (nu tot odata).

Ecranele scheletului sunt denumite și ca:

  • elemente fantomă,
  • substituenți de conținut,
  • încărcătoare de conținut.

Blockchain.com, YouTube, Facebook, Medium și alte companii mari de tehnologie afișează ecrane schelet în timp ce conținutul lor se încarcă pentru a stimula UX.

Blockchain.com

Interfața de utilizare a ecranului schelet Blockchain.com
Starea parțial încărcată a Blockchain.com (observați cum este utilizat un schelet în analiza graficului) (Previzualizare mare)

Mediu

Interfața de utilizare a ecranului cu schelet mediu
Interfața de utilizare a scheletului mediu (previzualizare mare)

LinkedIn

Interfața de utilizare a ecranului schelet LinkedIn
Starea de încărcare a feedului de acasă al LinkedIn în 2018 (previzualizare mare)

Tipuri de ecrane scheletice

Există diferite tipuri de ecrane scheletice. Cele mai importante sunt substituenții de text și substituenții de imagine (sau de culoare).

Majoritatea dezvoltatorilor preferă să folosească substituenți de text ca interfață de utilizare schelet în paginile lor, deoarece sunt ușor de construit, iar dezvoltatorul nu necesită detalii despre substanța conținutului real; în schimb scheletul imită UI.

Substituenții de culoare sunt mai greu de construit, deoarece necesită detalii despre conținut.

Unele pachete populare facilitează implementarea ecranelor schelet în aplicațiile web. Să aruncăm o privire mai atentă la ambele:

  • Substituent de reacție
  • Reacționează încărcând scheletul

Ne vom uita la avantajele și dezavantajele fiecărui pachet, înainte de a ne gândi pe care să folosim pentru aplicația noastră.

Substituent de reacție

Pro

  • Componentele substituenților sunt folosite pentru a crea o interfață de utilizare cu schelet personalizat.
  • Animația cu puls (adică efectul de mișcare asupra unui element) este acceptată.
  • Vine cu un API bazat pe componente.

Contra

  • Componentele scheletului sunt menținute separat, astfel încât actualizarea stilurilor unei componente necesită, eventual, actualizarea componentei scheletului.
  • Curba de învățare nu este liniară deoarece există mai multe componente pentru nevoi diferite.

Următorul este un exemplu de componentă schelet folosind pachetul react-placeholder :

 import { TextBlock, RectShape } from 'react-placeholder/lib/placeholders'; import ReactPlaceholder from 'react-placeholder'; const GhostPlaceholder = () => ( <div className='my-placeholder'> <RectShape color='gray' style={{width: 25, height: 70}} /> <TextBlock rows={6} color='blue'/> </div> ); <ReactPlaceholder ready={ready} customPlaceholder={<GhostPlaceholder />}> <MyComponent /> </ReactPlaceholder>

TextBlock și RectShape din react-placeholder/lib/placeholder și ReactPlaceholder din react-placeholder , am creat o componentă funcțională numită GhostPlaceholder . GhostPlaceholder are un div, iar în interiorul div-ului am folosit componenta RectShape, care descrie dimensiunile unui dreptunghi, transmite valoarea oricărei culori și definește stilurile dreptunghiului.

Apoi, am folosit componenta TextBlock pentru a seta valorile pentru rânduri și culoare. Componenta TextBlock definește numărul de rânduri și culoarea textului.

Trecem MyComponent ca un copil al componentei ReactPlaceholder , care primește ready și componenta GhostPlaceholder ca valori pentru elementele sale de recuzită ready și customPlaceholder .

MyComponent se va încărca când este afișată interfața de utilizare a ecranului schelet.

Pentru a afla mai multe, verificați documentația.

Reacționează încărcând scheletul

Pro

  • Este bazat pe API și are o componentă cu elemente de recuzită pentru toate personalizările.
  • Poate fi folosit ca o componentă schelet separată și, de asemenea, în interiorul oricărei componente direct, deci este flexibil.
  • Acceptă tematică și animație Pulse.

Contra

  • Este ușor de implementat pentru o interfață de utilizare schelet simplă, dar complicat pentru schelete mai complexe.
  • Având o componentă schelet separată, va fi mai dificil de întreținut atunci când interfața de utilizare și stilurile se schimbă.

Următorul este un exemplu de React Loading Skeleton:

 import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; const SkeletonComponent = () => ( <SkeletonTheme color="#202020" highlightColor="#444"> <section> <Skeleton height={50} width={50} /> </section> </SkeletonTheme> );

Am importat Skeleton și SkeletonTheme din biblioteca react-loading-skeleton , apoi am creat o componentă funcțională care redă componenta SkeletonTheme , cu color și hightlightColor ca proprietăți.

Componenta SkeletonTheme este utilizată pentru tematică (de exemplu, adăugarea de efecte de culoare la interfața de utilizare a scheletului).

În cele din urmă, în interiorul secțiunii, definim componenta Skeleton , cu proprietățile de înălțime și lățime și valorile lor corespunzătoare transmise.

Crearea unei interfețe de utilizare a ecranului schelet asemănătoare YouTube

Să creăm un ecran schelet asemănător YouTube, folosind React Loading Skeleton, pentru a arăta cum funcționează o interfață de utilizare schelet.

Configurați React

Cel mai simplu mod de a configura React este să utilizați aplicația Create React, care este „o modalitate acceptată oficial de a crea aplicații React cu o singură pagină. Oferă o configurație modernă, fără configurație.”

Îl vom folosi pentru a porni aplicația pe care o vom construi. De pe terminalul dvs., executați comanda de mai jos:

 npx create-react-app skeleton-screens && cd skeleton-screens

Odată ce instalarea s-a încheiat, porniți serverul React rulând npm start :

Aplicația React - Aplicația Scaffold React
Reacționează pagina de întâmpinare (previzualizare mare)

Creați interfața de utilizare YouTube fără un ecran schelet

Mai întâi, haideți să introducem date false YouTube. În mod normal, punctele finale reale ar fi folosite în loc de date fictive, dar în acest tutorial vom folosi date fictive.

Creați un fișier în folderul dvs. src/ și denumiți-l data.js , adăugați următorul cod la el.

 const dummyData= [ { section: "Recommended", channel: "CNN", items: [ { id: "fDObf2AeAP4", image: "https://img.youtube.com/vi/fDObf2AeAP4/maxresdefault.jpg", title: "75 million Americans ordered to stay home", views: "1.9M views", published: "3 days agos" }, { id: "3AzIgAa0Cm8", image: "https://img.youtube.com/vi/3AzIgAa0Cm8/maxresdefault.jpg", title: "Gupta: The truth about using chloroquine to fight coronavirus pandemic", views: "128K views", published: "4 hours ago" }, { id: "92B37aXykYw", image: "https://img.youtube.com/vi/92B37aXykYw/maxresdefault.jpg", title: "Willie Jones STUNS Simon Cowell In Pitch Perfect Performance of 'Your Man'!", views: "2.47 million views", published: "1 month ago" }, { id: "J6rVaFzOEP8", image: "https://img.youtube.com/vi/J6rVaFzOEP8/maxresdefault.jpg", title: "Guide To Becoming A Self-Taught Software Developer", views: "104K views", published: "17 days ago" }, { id: "Wbk8ZrfU3EM", image: "https://img.youtube.com/vi/Wbk8ZrfU3EM/maxresdefault.jpg", title: "Tom Hanks and Rita Wilson test positive for coronavirus", views: "600k views", published: "1 week ago" }, { id: "ikHpFgKJax8", image: "https://img.youtube.com/vi/ikHpFgKJax8/maxresdefault.jpg", title: "Faces Of Africa- The Jerry Rawlings story", views: "2.3 million views", published: "2014" } ] }, { section: "Breaking News", channel: "CGTN America", items: [ { id: "tRLDPy1A8pI", image: "https://img.youtube.com/vi/tRLDPy1A8pI/maxresdefault.jpg", title: "Is Trump blaming China for COVID-19? You decide.", views: "876k views", published: "9 days ago" }, { id: "2ulH1R9hlG8", image: "https://img.youtube.com/vi/2ulH1R9hlG8/maxresdefault.jpg", title: "Journalist still goes to office during pandemic, see her daily routine", views: "873 views", published: "3 hours ago" }, { id: "TkfQ9MaIgU", image: "https://img.youtube.com/vi/_TkfQ9MaIgU/maxresdefault.jpg", title: "How are small businesses going to survive the economic downturn of the COVID-19 era?", views: "283 views", published: "4 day ago" } ] } ]; export default dummyData;

Pentru a reproduce formatul YouTube, am creat date fictive care au o serie de obiecte, cu proprietăți precum ID, imagine, titlu, numărul de vizualizări și data publicării.

Apoi, să creăm interfața noastră de utilizare YouTube. Vom avea trei componente:

Card Conține detaliile miniaturii, titlului, numărul de vizionări, data publicării și canalul videoclipului.
CardList Returnează toate cărțile la rând.
App Montează obiectul nostru dummyData , încarcă interfața de utilizare schelet timp de două secunde și returnează componenta CardList .

În interiorul folderului src , creați un folder și denumiți-l components . În folderul components , creați un fișier Card.js , adăugați următorul cod la acesta:

 import React from "react"; const Card = ({ item, channel }) => { return ( <li className="card"> <a href={`https://www.youtube.com/watch?v=${item.id}`} target="_blank" rel="noopener noreferrer" className="card-link" > <img src={item.image} alt={item.title} className="card-image" /> <img src={item.image} alt={item.title} className="channel-image" /> <h4 className="card-title">{item.title}</h4> <p className="card-channel"> <i>{channel}</i> </p> <div className="card-metrics"> {item.views} • {item.published} </div> </a> </li> ); }; export default Card;

Am creat o componentă Card . În interiorul acestuia, am importat React din react și am deconstruit item și elementele de recuzită ale channel astfel încât acestea să poată fi folosite în componenta Card . Fiecare componentă a articolului Card care afișează un videoclip va afișa miniatura, numărul de vizualizări, data publicării și titlul.

Componenta CardList

În interiorul folderului components , creați un fișier CardList.js și adăugați următorul cod la acesta:

 import React from "react"; import Card from "./Card"; const CardList = ({ list }) => { return ( <ul className="list"> {list.items.map((item, index) => { return <Card key={index} item={item} channel={list.channel} />; })} </ul> ); }; export default CardList;

În această componentă, am importat componenta Card pe care am creat-o. Cardul acceptă item și elementele de recuzită ale channel , pe care le obținem prin maparea prin list.items . Exportăm apoi această componentă ca CardList , deoarece o vom folosi în componenta noastră App .

Notă : Matricea de articole care este mapată în această componentă este matricea de obiecte din dummyData .

Componenta aplicației

În interiorul fișierului app.js din directorul src/ , ștergeți codul care se află acolo și adăugați următoarele.

 import React, { useState, useEffect } from "react"; import "./App.css"; import dummyData from "./data"; import CardList from "./components/CardList"; const App = () => { const [videos, setVideos] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { setLoading(true); const timer = setTimeout(() => { setVideos(dummyData); setLoading(false); }, 5000); return () => clearTimeout(timer); }, []); return ( <div className="App"> { videos.map((list, index) => { return ( <section key={index}> <h2 className="section-title">{list.section}</h2> <CardList list={list} /> <hr /> </section> ); })} </div> ); }; export default App;

În această componentă, am importat cârligele useState și useEffect alături de React și alte fișiere pe care le-am creat și care vor fi necesare în componenta App .

Deoarece datele noastre sunt date fictive, trebuie să le facem joc ca și datele API, încărcând conținutul după un timeout de două secunde, folosind metoda JavaScript setTimeout .

Apoi, în componenta App , creăm o stare video și setăm starea la o matrice goală folosind useState .

Pentru a încărca datele noastre fictive, vom folosi cârligul useEffect . În cârligul nostru, creăm un temporizator variabil care deține funcția setTimeout () . În cadrul funcției, ne setăm starea video la obiectul nostru dummyData și ne asigurăm că datele se încarcă după două secunde și, în sfârșit, anulăm temporizatorul în timpul demontării.

În cele din urmă, mapăm starea noastră video și returnăm elementul de secțiune care conține secțiunea list-section și componenta CardList cu elementele sale de recuzită.

Adăugarea CSS

Până acum, am folosit o mulțime de clase fără CSS real. În interiorul folderului src , ștergeți totul din App.css și înlocuiți-l cu următorul cod;

 .App { max-width: 960px; margin: 0 auto; font-size: 16px; } .list { display: flex; justify-content: space-between; flex-wrap: wrap; list-style: none; padding: 0; } .section-title { margin-top: 30px; } .card { width: calc(33% - 10px); margin: 20px 0; } .card-link { color: inherit; text-decoration: none; } .card-image { width: 100%; } .channel-image { border-radius: 100%; padding: 0, 10px, 0, 0; width: 40px; height: 40px; } .card-title { margin-top: 10px; margin-bottom: 0; } .card-channel { margin-top: 5px; margin-bottom: 5px; font-size: 14px; } /* Tablets */ @media (max-width: 1000px) { .App { max-width: 600px; } .card { width: calc(50% - 22px); } } /* Mobiles \*/ @media (max-width: 640px) { .App { max-width: 100%; padding: 0 15px; } .card { width: 100%; } }

Să vedem cum arată interfața noastră de utilizare YouTube fără ecranul schelet. Puteți vedea că atunci când pagina se încarcă, apare un ecran alb timp de două secunde, apoi datele se încarcă prompt.

Interfață de utilizare asemănătoare YouTube fără ecran schelet
Interfață de utilizare similară cu YouTube fără ecran schelet (previzualizare mare)

Folosind React Loading Skeleton

Spre deosebire de alte biblioteci în care ați crea cu meticulozitate un ecran schelet pentru a se potrivi cu dimensiunile fontului, înălțimile liniilor și marginile conținutului dvs., componenta Skeleton este concepută pentru a fi utilizată direct în componentele dvs., în locul conținutului care se încarcă.

Să trecem peste câteva motive pentru care am ales React Loading Skeleton în locul altora.

Tematică

React Loading Skeleton acceptă tematica. Astfel, puteți schimba cu ușurință culorile tuturor componentelor scheletului utilizând SkeletonTheme și transmiteți valori la elementele de props de culoare.

Mai jos este un exemplu care arată cum funcționează:

 import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; <SkeletonTheme color="grey" highlightColor="#444"> <p> <Skeleton height={250} width={300} count={1} /> </p> </SkeletonTheme> <SkeletonTheme color="#990" highlightColor="#550"> <p> <Skeleton height={250} width={300} count={1} /> </p> </SkeletonTheme> 
Efectul de tematică în acțiune
Efect de tematică în acțiune (previzualizare mare)

Durată

Pe lângă elementele de recuzită height , width și color , putem specifica și o recuzită pentru duration .

 <Skeleton duration={2} />

Durata este implicită la 1.2 . Aceasta determină cât timp durează pentru a face un ciclu al animației scheletului.

Pentru a afla mai multe, consultați documentația.

Implementarea Skeleton Screen UI

Acum, vom instala react-loading-skeleton . Rulați următoarea comandă în terminalul dvs. pentru a instala pachetul:

 npm install react-loading-skeleton

Componenta scheletului

Să creăm o componentă schelet pentru datele noastre video. În dosarul nostru de components , creați un fișier SkeletonCard.js și adăugați următorul cod:

 import React from "react"; import Skeleton from "react-loading-skeleton"; const SkeletonCard = () => { return ( <section> <h2 className="section-title"> <Skeleton height={30} width={300} /> </h2> <ul className="list"> {Array(9) .fill() .map((item, index) => ( <li className="card" key={index}> <Skeleton height={180} /> <h4 className="card-title"> <Skeleton circle={true} height={50} width={50} />  <Skeleton height={36} width={`80%`} /> </h4> <p className="card-channel"> <Skeleton width={`60%`} /> </p> <div className="card-metrics"> <Skeleton width={`90%`} /> </div> </li> ))} </ul> </section> ); }; export default SkeletonCard;

Am creat o listă neordonată. În interiorul acestuia, am folosit metoda Array.fill() . Deoarece avem nouă elemente de date fictive, am folosit metoda Array.fill() pentru a parcurge lungimea obiectului nostru items și l-am umplut fără valoare de index, făcând astfel matricea noastră goală . Consultați documentația Array.fill pentru a afla cum funcționează.

Apoi, am mapat prin matricea noastră goală pentru a returna o listă care conține proprietățile scheletului și am specificat valoarea fiecăreia dintre proprietățile scheletului.

Aici, height conotă lungimea unui dreptunghi schelet, iar width se referă la lățime, în timp ce circle creează partea rotunjită a interfeței de utilizare a scheletului.

React Loading Skeleton vine cu o animație implicită Pulse, ceea ce o face la îndemână. Ai putea crea o animație Pulse pentru a se potrivi proiectului tău, dar dacă mă întrebi, aș rămâne cu cea implicită.

În cele din urmă, codul sursă complet este disponibil.

Acum avem o interfață de utilizare a ecranului schelet complet funcțională. Exemplul nostru arată scheletul timp de cinci secunde înainte de a afișa conținutul.

Să vedem rezultatul nostru de până acum:

Interfață de utilizare asemănătoare YouTube plus interfață de utilizare a ecranului schelet
Interfața noastră de utilizare schelet asemănătoare YouTube (previzualizare mare)

Concluzie

Ecranele schelet îmbunătățesc enorm experiența utilizatorului, evitând frustrarea de a se confrunta cu un ecran complet gol și oferind utilizatorului o impresie despre cum va arăta conținutul înainte de a se încarca.

Dacă nu vă simțiți confortabil cu niciunul dintre pachetele pe care le-am analizat, vă puteți crea propria interfață de utilizare schelet făcând dreptunghiuri și cercuri care imită aspectul paginii.

Vă rugăm să împărtășiți feedbackul și experiența dvs. în secțiunea de comentarii de mai jos. Mi-ar plăcea să văd cu ce ai venit!

Repo de sprijin pentru acest articol este disponibil pe Github.

Referințe

  • „Tot ce trebuie să știți despre ecranele schelet”, Bill Chung, UX Collective
  • „Skeleton Loading Pages With React”, Anthony Panagi, Octopus Wealth
  • „Scheleton Screens With React And React Native”, Chris Dolphin, Alligator.io
  • „Implementarea Skeleton Loading In React”, Adrian Bece, DEV