Ractive.js - Aplicații web simplificate

Publicat: 2022-03-11

În peisajul de azi cu proliferare rapidă de cadre și biblioteci JavaScript, selectarea celui pe care doriți să vă bazați dezvoltarea poate fi o provocare. La urma urmei, odată ce parcurgeți calea utilizării unui anumit cadru, migrarea codului dvs. la utilizarea unuia diferit este o sarcină non-trivială pe care este posibil să nu aveți niciodată timpul sau bugetul s-o efectuați.

Deci, de ce Ractive.js?

Spre deosebire de alte instrumente care generează HTML inert, Ractive transformă șabloanele în planuri pentru aplicațiile care sunt interactive în mod implicit. Și deși s-ar putea argumenta cu siguranță că contribuția lui Ractive este mai evolutivă decât revoluționară, valoarea sa este totuși semnificativă.

Ceea ce face ca Ractive să fie atât de util este că oferă capabilități puternice, dar face acest lucru într-un mod care este înviorător de simplu de utilizat pentru dezvoltator. În plus, este destul de elegant, rapid, discret și mic.

În acest articol, vom parcurge procesul de construire a unei aplicații de căutare simple Ractive, demonstrând unele dintre caracteristicile cheie ale Ractive și modurile în care ajută la simplificarea aplicațiilor web și a dezvoltării.

Ractive.js și aplicații web

Ce este Ractive.js?

Ractive a fost creat inițial pentru a aborda problema legată de date într-un mod mai elegant. În acest scop, este nevoie de șabloane și le transformă într-o reprezentare virtuală ușoară a DOM-ului, astfel încât, atunci când datele se schimbă, DOM-ul real să fie actualizat inteligent și eficient.

Dar curând a devenit evident că abordarea și infrastructura folosite de Ractive ar putea fi folosite pentru a face și alte lucruri mai eficient. Poate, de exemplu, să se ocupe automat de lucruri precum reutilizarea gestionatorilor de evenimente și dezlegarea automată a acestora atunci când nu mai sunt necesare. Delegarea evenimentului devine inutilă. Ca și în cazul legării de date, această abordare împiedică codul să devină greoi pe măsură ce o aplicație crește.

Caracteristicile cheie, cum ar fi legarea bidirecțională, animațiile și suportul SVG, sunt furnizate imediat, iar funcționalitatea personalizată poate fi adăugată cu ușurință prin intermediul pluginurilor.

În timp ce unele instrumente și cadre vă obligă să învățați un vocabular nou și să vă structurați aplicația într-un anumit mod, Ractive funcționează pentru dvs., nu invers. De asemenea, se integrează bine cu alte biblioteci.

Aplicația noastră de probă

Aplicația noastră eșantion va fi folosită pentru a căuta în baza de date Toptal a dezvoltatorilor pe baza abilităților. Aplicația noastră va avea două vizualizări:

  • Căutare: listă de abilități cu casetă de căutare inline
  • Rezultate: vizualizarea abilităților, inclusiv lista de dezvoltatori

Pentru fiecare dezvoltator, îi vom afișa numele, fotografia, o scurtă descriere și o listă de abilități (fiecare abilitate va fi conectată la vizualizarea abilităților corespunzătoare).

(Notă: linkurile către o instanță de lucru online a aplicației și depozitul de cod sursă sunt ambele furnizate la sfârșitul acestui articol.)

Pentru a ne menține concentrarea principală asupra cadrului Ractive, vom folosi o serie de simplificări care în mod normal nu ar trebui făcute în producție:

  • Tema implicită. Vom folosi Bootstrap cu tema implicită pentru stil, în loc să personalizăm tema pentru a se potrivi stilului aplicației dvs.
  • Dependente. Vom adăuga dependențele noastre ca scripturi separate care definesc variabile globale (în loc să folosim module ES6, sau CommonJS sau AMD cu încărcătorul adecvat pentru dezvoltare și pasul de construire pentru producție).
  • Date statice. Vom folosi datele statice pe care le-am pregătit prin răzuirea paginilor publice de pe site-ul Toptal.
  • Fără rutare pe partea clientului. Aceasta înseamnă că adresa URL va rămâne aceeași pe măsură ce comutăm între vizualizări. Cu siguranță nu ar trebui să faceți asta pentru SPA-uri, deși poate fi OK pentru unele componente interactive mici. Ractive nu are o implementare de router încorporată, dar poate fi utilizat cu routere terță parte, așa cum se arată în acest exemplu.
  • Șabloane definite în interiorul etichetelor de script în HTML. Aceasta nu este neapărat o idee rea, mai ales pentru aplicațiile mici și are câteva avantaje (este simplu și puteți procesa aceste șabloane de la parte client împreună cu șabloanele de pe partea de server, de exemplu pentru internaționalizare). Dar pentru aplicațiile mai mari ați putea beneficia de pre-compilare (alias, pre-analizarea șabloanelor la reprezentarea JS internă.

Să începem cu aplicațiile web

OK, așa că, cu acestea spuse, să începem să construim aplicația. O vom face într-o manieră iterativă, adăugând caracteristici mai mici una câte una și explorând conceptele pe măsură ce le întâlnim.

Să începem prin a crea un folder cu două fișiere în interior: index.html și script.js . Aplicația noastră va fi extrem de simplă și va funcționa din protocolul file:// pentru a evita necesitatea pornirii serverului de dezvoltare (deși puteți dacă doriți).

Pagina de căutare

Vom începe prin a implementa pagina de căutare în care utilizatorul poate selecta o abilitate pentru care să găsească dezvoltatorii potriviți în baza de date Toptal.

Scheletul HTML

Să începem cu această pagină HTML banală:

 <html> <head> <title>Toptal Search</title> <!-- LOAD BOOTSTRAP FROM THE CDN --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> </head> <body> <!-- SOME BASIC STATIC CONTENT --> <div class="container"> <h1>Toptal Search</h1> </div> <!-- LOAD THE JAVASCRIPT LIBRARIES WE NEED --> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ractive/0.7.3/ractive.min.js"></script> <!-- LOAD THE DATA --> <script src="https://rawgit.com/emirotin/toptal-blog-ractive/master/data.js"></script> <!-- LOAD OUR SCRIPT --> <script src="script.js"></script> </body> </html>

După cum puteți vedea, este un document HTML5 banal. Încarcă Bootstrap din CDN, Lodash (o bibliotecă minunată de manipulare a datelor) și Ractive.js.

Ractive nu necesită dedicarea întregii pagini la SPA, așa că putem avea un conținut static. În cazul nostru, acesta constă dintr-un element container și titlul paginii.

În cele din urmă, încărcăm datele pe care le-am pregătit pentru demo și scriptul care va conține programul nostru.

OK, acum că scheletul nostru HTML este la locul lui, să începem să adăugăm niște funcționalități reale.

Lista de aptitudini

Unul dintre lucrurile care îmi plac în mod deosebit la Ractive este modul în care vă învață să vă gândiți la reprezentarea finală (HTML) pe care doriți să o obțineți și apoi vă permite să vă concentrați pe scrierea fragmentelor de cod necesare pentru a realiza acest lucru.

Deci, mai întâi, să construim o listă de abilități ca viziunea noastră inițială. A face acest lucru presupune pur și simplu:

  • Adăugarea unui element HTML în care va fi afișată lista de aptitudini.
  • Adăugarea unui mic fragment de cod șablon la HTML-ul nostru.
  • Scrierea unui JavaScript scurt și simplu care furnizează datele șablonului, pentru a-l reda în elementul HTML pe care l-am adăugat.

Modificările la HTML constau în următoarele:

 <div class="container"> <h1>Toptal Search</h1> <div></div> <!-- THIS IS THE NEW HTML ELEMENT --> </div> <!-- THIS IS THE SMALL SNIPPET OF TEMPLATE CODE --> <script type="text/html"> <div class="row"> {{#each skills}} <span class="col-xs-3"> <a href="#" class="label label-primary">{{this}}</a> </span> {{/each}} </div> </script>

Nu există o convenție specială cu Ractive pentru specificarea elementului HTML pentru a primi datele de afișat, dar cel mai simplu mod de a face acest lucru este să adăugați un ID elementului. De obicei folosesc ID-ul „rădăcină” în acest scop. Vom vedea în curând cum este folosit când Ractive este inițializat. Pentru cei curioși există și alte modalități de a specifica elementul rădăcină.

Elementul de script ușor incomod cu type="text/html" este un truc inteligent pentru a obține o bucată de HTML încărcată de browser fără ca acesta să fie analizat sau randat, deoarece browserele ignoră scripturile de tip necunoscut. Conținutul scriptului este un șablon asemănător mustață/ghinionului (deși Ractive are unele extensii).

Mai întâi scriem codul șablon presupunând că avem acces la matricea de abilități. Folosim directiva mustață {{#each}} pentru a defini iterația. În interiorul directivei, elementul curent poate fi accesat this . Din nou, presupunem că variabila competențe deține o matrice de șiruri, așa că pur și simplu o redăm cu o mustață de interpolare {{this}} .

OK, acesta este HTML-ul. Dar ce zici de JavaScript? Acolo se întâmplă „magia” care furnizează datele șablonului::

 (function () { var skills = DB.skills, developers = DB.developers; var app = new Ractive({ el: '#root', template: '#tpl-app', data: { skills: _.keys(DB.skills) } }); }());

Impresionant, nu? În doar acele 10 linii de cod suntem capabili să:

  1. „Preluați” datele din „DB”.
  2. Instanciați o nouă aplicație Ractive.
  3. Spune-i să redea în interiorul elementului cu .
  4. Spune-i să folosească un element de script cu pentru a obține șablonul (există și alte moduri de a face acest lucru).
  5. Transmiteți datele inițiale (vom vedea cum să le schimbăm în timpul execuției) sau „domeniul de aplicare” dacă sunteți obișnuit cu terminologia Angular.
  6. Utilizați metoda keys lodash pentru a obține numele abilităților pe care le folosim ca chei obiect în „DB”.

Deci, practic, cu acest script îi spunem cadrului ce să facă, dar nu cum să o facă. Șablonul declară cum, ceea ce personal mi se pare destul de uimitor și natural.

Sperăm că începeți să înțelegeți ideea, așa că acum să implementăm ceva mai util pe lângă ceea ce avem.

Căutare de aptitudini

Pagina de căutare, desigur, are nevoie de un câmp de căutare. Și ne-am dori să ofere o capacitate interactivă prin care, pe măsură ce utilizatorul tasta în caseta de căutare, lista de abilități este filtrată în jos include doar cele care conțin subșirul introdus (filtrarea fiind insensibilă la majuscule).

Ca de obicei cu Ractive, începem prin a defini șablonul (în timp ce ne gândim ce noi variabile de context vor fi necesare și ce s-ar schimba în ceea ce privește gestionarea datelor):

 <div class="container"> <h1>Toptal Search</h1> <div></div> </div> <!-- THIS IS THE SMALL SNIPPET OF TEMPLATE CODE --> <script type="text/html"> <!-- HERE'S OUR SEARCH BOX --> <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <!-- NOW INSTEAD OF DISPLAYING ALL SKILLS, WE INVOKE A TO-BE-CREATED JAVASCRIPT skills() FUNCTION THAT WILL FILTER THE SKILL LIST DOWN TO THOSE THAT MATCH THE TEXT ENTERED BY THE USER --> <div class="row"> {{#each skills()}} <span class="col-xs-3"> <a href="#" class="label label-primary">{{this}}</a> </span> {{/each}} </div> </script>

Nu atât de multe schimbări, dar încă o sumă bună de învățat.

În primul rând, am adăugat un nou <div> care conține caseta noastră de căutare. Este destul de evident că vrem să conectăm acea intrare la o variabilă (cu excepția cazului în care sunteți nostalgic de zilele bune de supă jQuery). Ractive acceptă așa-numita legare în două sensuri, ceea ce înseamnă că codul dvs. JS poate prelua o valoare fără a fi nevoie să o citiți manual din DOM. În cazul nostru, acest lucru se realizează prin utilizarea value="{{ skillFilter }}" . Ractive înțelege că vrem să legăm această variabilă de atributul value al intrării. Deci urmărește intrarea pentru noi și actualizează automat variabila. Destul de îngrijit cu doar o linie de HTML.

În al doilea rând, așa cum este explicat în comentariul din fragmentul de cod de mai sus, acum, în loc să afișăm toate abilitățile, vom crea o funcție JS skills() care va filtra lista de abilități și va returna doar cele care se potrivesc cu textul introdus de utilizator:

 // store skill list in a variable outside of Ractive scope var skillNames = _.keys(DB.skills); var app = new Ractive({ el: '#root', template: '#tpl-app', data: { // initializing the context variable is not strictly // required, but it is generally considered good practice skillFilter: null, // Define the skills() function right in our data object. // Function is available to our template where we call it. skills: function() { // Get the skillFilter variable from the Ractive instance // (available as 'this'). // NOTE WELL: Our use of a getter here tells Ractive that // our function has a *dependency* on the skillFilter // value, so this is significant. var skillFilter = this.get('skillFilter'); if (!skillFilter) { return skillNames; } skillFilter = new RegExp(_.escapeRegExp(skillFilter), 'i') return _.filter(skillNames, function(skill) { return skill.match(skillFilter); }); } } });

Deși acest lucru este curat și simplu de implementat, s-ar putea să vă întrebați cum afectează performanța. Adică, vom apela o funcție de fiecare dată? Ei bine, de fiecare dată ce? Ractive este suficient de inteligent pentru a reda doar părți ale șablonului (și a apela orice funcții din ele) atunci când dependențele (variabilele) acestora se schimbă (Ractive știe când se întâmplă asta datorită utilizării settorilor).

De altfel, pentru cei interesați să facă acest lucru un pas mai departe, există și o modalitate mai elegantă de a face acest lucru folosind o proprietate calculată, dar vă voi lăsa să vă jucați singur, dacă doriți.

Pagina de rezultate

Acum că avem o listă de abilități care poate fi căutată destul de utilizabilă, să trecem la vizualizarea rezultatelor unde va fi afișată lista de dezvoltatori care se potrivesc.

Comutarea la și de la vizualizarea abilităților

Există, evident, mai multe moduri în care acest lucru ar putea fi implementat. Am selectat abordarea de a exista două puncte de vedere diferite, în funcție de dacă a fost selectată sau nu o abilitate. Dacă da, arătăm lista dezvoltatorilor care se potrivesc; dacă nu, arătăm lista de aptitudini și caseta de căutare.

Deci, pentru început, atunci când utilizatorul selectează (adică face clic pe) un nume de abilitate, lista de abilități trebuie să fie ascunsă, iar numele abilității ar trebui afișat în schimb ca titlu de pagină. În schimb, în ​​vizualizarea abilităților selectate, trebuie să existe o modalitate de a închide acea vizualizare și de a reveni la lista de abilități.

Iată primul nostru pas pe această cale:

 <script type="text/html"> <!-- PARTIAL IS A NEW CONCEPT HERE --> {{#partial skillsList}} <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <div class="row"> {{#each skills()}} <span class="col-xs-3"> <!-- MAKE OUR SKILLS CLICKABLE, USING PROXY EVENTS --> <a href="#" class="label label-primary" on-click="select-skill:{{this}}">{{this}}</a> </span> {{/each}} </div> {{/partial}} {{#partial skillView}} <h2> <!-- DISPLAY SELECTED SKILL AS HEADING ON THE PAGE --> {{ currentSkill }} <!-- CLOSE BUTTON TAKES USER BACK TO SKILLS LIST --> <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{/partial}} <!-- PARTIALS ARE NOT IN THE VIEW UNTIL WE EXPLICITLY INCLUDE THEM, SO INCLUDE THE PARTIAL RELEVANT TO THE CURRENT VIEW. --> {{#if currentSkill}} {{> skillView}} {{else}} {{> skillsList}} {{/if}} </script>

OK, se întâmplă MULTE aici.

În primul rând, pentru a permite implementarea acestui lucru ca două vederi diferite, am mutat tot ceea ce aveam până acum (adică, vizualizarea listă) la ceva numit parțial. Un parțial este în esență o bucată de cod șablon pe care o vom include într-un loc diferit (în curând).

Apoi, dorim să facem clic pe abilitățile noastre, iar atunci când facem clic, vrem să navigăm la vizualizarea abilităților corespunzătoare. Pentru aceasta, folosim ceva numit evenimente proxy, prin care reacționăm la un eveniment fizic (la clic, numele este cel ușor de înțeles de Ractive) și îl trimitem la evenimentul logic (select-skill, numele este cum îl numim). ) trecând argumentul (după cum probabil vă amintiți, acesta înseamnă aici numele aptitudinii).

(FYI, există o sintaxă alternativă a apelurilor de metodă pentru a realiza același lucru.)

În continuare, presupunem (din nou) că vom avea o variabilă numită currentSkill care va avea numele aptitudinii selectate (dacă există), sau va fi goală dacă nu sunt selectate competențe. Deci definim un alt parțial care arată numele actual al aptitudinii și, de asemenea, are un link „ÎNCHIS” care ar trebui să deselecteze competența.

Pentru JavaScript, principala adăugare este codul de abonare la evenimentele select-skill și deselect-skill, actualizând currentSkill (și skillFilter ) în consecință:

 var app = new Ractive({ el: '#root', template: '#tpl-app', data: { skillFilter: null, currentSkill: null, // INITIALIZE currentSkill TO null // skills function remains unchanged skills: function() { var skillFilter = this.get('skillFilter'); if (!skillFilter) { return skillNames; } skillFilter = new RegExp(_.escapeRegExp(skillFilter), 'i') return _.filter(skillNames, function(skill) { return skill.match(skillFilter); }); } } }); // SUBSCRIBE TO LOGICAL EVENT select-skill app.on('select-skill', function(event, skill) { this.set({ // SET currentSkill TO THE SKILL SELECTED BY THE USER currentSkill: skill, // RESET THE SEARCH FILTER skillFilter: null }); }); // SUBSCRIBE TO LOGICAL EVENT deselect-skill app.on('deselect-skill', function(event) { this.set('currentSkill', null); // CLEAR currentSkill });

Listarea dezvoltatorilor pentru fiecare abilitate

După ce am pregătit noua vizualizare pentru abilitate, acum putem adăuga puțină carne - lista reală de dezvoltatori pe care o avem pentru acea listă. Pentru aceasta, extindem parțialul pentru această vizualizare după cum urmează:

 {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body"> {{ this.name }} </div> </div> {{/each}} {{/partial}}

Sperăm că, până în acest moment, veți înțelege ce se întâmplă aici: am adăugat o nouă secțiune de iterație la parțialul nostru skillView care iterează peste rezultatul unei noi funcții skillDevelopers pe care o vom scrie imediat în continuare. Pentru fiecare dezvoltator din matrice (returnat de acea skillDevelopers ), redăm un panou și afișăm numele dezvoltatorului. Rețineți că aș putea folosi forma implicită {{name}} aici și Ractive ar găsi atributul potrivit căutând lanțul de context pornind de la contextul curent (care în cazul nostru este obiectul dezvoltator legat de {{#each}} ), dar Prefer să fiu explicit. Mai multe informații despre contexte și referințe sunt disponibile în documentația Ractive.

Și iată implementarea funcției skillDevelopers() :

 skillDevelopers: function(skill) { // GET THE SKILL OBJECT FROM THE “DB” skill = skills[skill]; // SAFETY CHECK, RETURN EARLY IN CASE OF UNKNOWN SKILL NAME if (!skill) { return; } // MAP THE DEVELOPER'S IDs (SLUGS) TO THE // ACTUAL DEVELOPER DETAIL OBJECTS return _.map(skill.developers, function(slug) { return developers[slug]; }); }

Extinderea intrării pentru fiecare dezvoltator

Acum că avem o listă de lucru a dezvoltatorilor, este timpul să adăugăm mai multe detalii și, desigur, o fotografie frumoasă:

 {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body media"> <div class="media-left"> <!-- ADD THE PHOTO --> <img class="media-object img-circle" width="64" height="64" src="{{ this.photo }}" alt="{{ this.name }}"> </div> <div class="media-body"> <!-- MAKE THE DEVELOPER'S NAME A HYPERLINK TO THEIR PROFILE --> <a class="h4 media-heading" href="{{ this.url }}" target="_blank"> {{ this.name }}</a> <!-- ADD MORE DETAILS (FROM THEIR PROFILE) --> <p>{{ this.desc }}</p> </div> </div> </div> {{/each}} {{/partial}}

Nimic nou aici din partea Ractive a lucrurilor, dar o utilizare puțin mai intensă a funcțiilor Bootstrap.

Afișarea unei liste de abilități de dezvoltator pe care se poate face clic

Am făcut progrese bune până acum, dar o caracteristică care încă lipsește este cealaltă parte a relației abilități-dezvoltator; și anume, dorim să afișăm abilitățile fiecărui dezvoltator și dorim ca fiecare dintre acele abilități să fie un link pe care se poate face clic care ne duce la vizualizarea rezultatelor pentru acea abilitate.

Dar stai... Sunt sigur că avem deja exact același lucru în lista de abilități. Da, de fapt, o facem. Se află în lista de abilități pe care se poate face clic, dar provine dintr-o matrice diferită de setul de abilități al fiecărui dezvoltator. Cu toate acestea, acestea sunt suficient de asemănătoare încât este un semn clar pentru mine că ar trebui să reutilizam acea bucată de HTML. Și spre acest scop, parțialele sunt prietenele noastre.

(Notă: Ractive are, de asemenea, o abordare mai avansată pentru bucăți reutilizabile de vedere, cunoscute sub numele de componente. Sunt într-adevăr destul de utile, dar de dragul simplității, nu le vom discuta acum.)

Așadar, iată cum realizăm acest lucru folosind parțiale (și rețineți, de altfel, că putem adăuga această funcționalitate fără a adăuga o singură linie de cod JavaScript!):

 <!-- MAKE THE CLICKABLE SKILL LINK INTO ITS OWN “skill” PARTIAL --> {{#partial skill}} <a href="#" class="label label-primary" on-click="select-skill:{{this}}">{{this}}</a> {{/partial}} {{#partial skillsList}} <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <div class="row"> {{#each skills()}} <!-- USE THE NEW “skill” PARTIAL --> <span class="col-xs-3">{{> skill}}</span> {{/each}} </div> {{/partial}} {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body media"> <div class="media-left"> <img class="media-object img-circle" width="64" height="64" src="{{ this.photo }}" alt="{{ this.name }}"> </div> <div class="media-body"> <a class="h4 media-heading" href="{{ this.url }}" target="_blank">{{ this.name }}</a> <p>{{ this.desc }}</p> <p> <!-- ITERATE OVER THE DEVELOPER'S SKILLS --> {{#each this.skills}} <!-- REUSE THE NEW “skill” PARTIAL TO DISPLAY EACH DEVELOPER SKILL AS A CLICKABLE LINK --> {{> skill}}&nbsp; {{/each}} </p> </div> </div> </div> {{/each}} {{/partial}}

Am deja lista de abilități atașată la obiectul dezvoltatorului pe care l-am preluat din „DB”, așa că doar am schimbat puțin șablonul: am mutat linia care redă eticheta de abilități într-un parțial și am folosit acest parțial acolo unde a fost linia inițială.

Apoi, când repetă peste abilitățile dezvoltatorului, pot reutiliza același nou parțial pentru a afișa fiecare dintre aceste abilități și ca link pe care se poate face clic. Mai mult, acest lucru indică și evenimentul select-skill, dacă vă amintiți, trecând același nume de abilitate. Aceasta înseamnă că putem include acest lucru oriunde (având contextul adecvat) și vom obține o etichetă pe care se poate face clic care duce la vizualizarea abilităților!

Final Touch — Preîncărcare

OK, acum avem o aplicație funcțională de bază. Este curat și funcționează rapid, dar încă durează ceva timp pentru a se încărca. (În cazul nostru, acest lucru se datorează parțial că folosim surse neconcatenate, neminificate, dar într-o aplicație din lumea reală pot exista și alte motive semnificative, cum ar fi încărcarea datelor inițiale).

Deci, ca un ultim pas, vă voi arăta un truc frumos pentru a adăuga o animație de preîncărcare care va fi eliminată de îndată ce Ractive redă aplicația noastră:

 <div class="container"> <h1>Toptal Search</h1> <div> <div class="progress"> <div class="progress-bar progress-bar-striped active"> Loading... </div> </div> </div> </div>

Deci, care este magia aici? De fapt, este destul de simplu. Am adăugat ceva conținut (este o bară de progres animată Bootstrap, dar ar putea fi un GIF animat sau orice altceva) direct la elementul nostru rădăcină. Cred că este destul de inteligent - în timp ce scripturile noastre se încarcă, utilizatorul vede indicatorul de încărcare (din moment ce nu are nicio dependență de JavaScript, poate fi afișat imediat). Cu toate acestea, de îndată ce aplicația Ractive este inițializată, Ractive va suprascrie conținutul elementului rădăcină (și, prin urmare, va șterge animația de preîncărcare) cu șablonul redat. În acest fel, putem obține acest efect doar o bucată de HTML static și 0 linii de logică. Cred că e destul de mișto.

Concluzie

Gândiți-vă la ceea ce am realizat aici și cât de ușor l-am realizat. Avem o aplicație destul de cuprinzătoare: arată o listă de abilități, permite căutarea rapidă printre ele (și chiar acceptă actualizarea interactivă a listei de abilități pe măsură ce utilizatorul scrie în caseta de căutare), permite navigarea la o anumită abilitate și înapoi și liste dezvoltatorii pentru fiecare abilitate selectată. În plus, putem face clic pe orice abilitate listată de orice dezvoltator pentru a ne duce la lista de dezvoltatori cu acea abilitate. Și toate acestea cu mai puțin de 80 de linii de HTML și mai puțin de 40 de linii de JavaScript. În opinia mea, este destul de impresionant și spune multe despre puterea, eleganța și simplitatea lui Ractive.

O versiune funcțională a aplicației este disponibilă online aici, iar codul sursă complet este public și disponibil aici.

Desigur, abia am zgâriat suprafața în acest articol a ceea ce este posibil cu cadrul Ractive. Dacă îți place ceea ce ai văzut până acum, te încurajez să începi cu configurarea Ractive de 60 de secunde și să începi să explorezi singur tot ceea ce Ractive are de oferit.