Ractive.js - App Web semplificate

Pubblicato: 2022-03-11

Nel panorama odierno in rapida proliferazione di framework e librerie JavaScript, selezionare quello su cui si desidera basare il proprio sviluppo può essere una vera sfida. Dopotutto, una volta che hai seguito il percorso dell'utilizzo di un particolare framework, la migrazione del codice all'utilizzo di uno diverso è un'attività non banale che potresti non avere mai il tempo o il budget per eseguire.

Allora, perché Ractive.js?

A differenza di altri strumenti che generano HTML inerte, Ractive trasforma i modelli in progetti per app interattive per impostazione predefinita. E mentre si potrebbe certamente sostenere che il contributo di Ractive sia più evolutivo che rivoluzionario, il suo valore è comunque significativo.

Ciò che rende Ractive così utile è che fornisce potenti capacità, ma lo fa in un modo che è piacevolmente semplice da usare per lo sviluppatore. Inoltre, è abbastanza elegante, veloce, discreto e piccolo.

In questo articolo, illustreremo il processo di creazione di una semplice app di ricerca Ractive, dimostrando alcune delle funzionalità chiave di Ractive e i modi in cui aiuta a semplificare lo sviluppo e le app Web.

Ractive.js e app web

Cos'è Ractive.js?

Ractive è stato originariamente creato per affrontare il problema del data binding in un modo più elegante. A tal fine, prende i modelli e li trasforma in una leggera rappresentazione virtuale del DOM in modo che, quando i dati cambiano, il vero DOM venga aggiornato in modo intelligente ed efficiente.

Ma divenne presto evidente che l'approccio e l'infrastruttura impiegati da Ractive potevano essere usati anche per fare altre cose in modo più efficiente. Ad esempio, può occuparsi automaticamente di cose come riutilizzare i gestori di eventi e annullarli automaticamente quando non sono più necessari. La delega dell'evento diventa superflua. Come con l'associazione dati, questo approccio impedisce al codice di diventare ingombrante man mano che un'app cresce.

Le funzionalità chiave come rilegatura a due vie, animazioni e supporto SVG sono fornite immediatamente e funzionalità personalizzate possono essere facilmente aggiunte tramite plug-in.

Mentre alcuni strumenti e framework ti costringono ad apprendere un nuovo vocabolario e a strutturare la tua app in un modo particolare, Ractive funziona per te, non il contrario. Si integra bene anche con altre librerie.

La nostra app di esempio

La nostra app di esempio verrà utilizzata per cercare nel database Toptal degli sviluppatori in base alle competenze. La nostra app avrà due viste:

  • Cerca: elenco delle competenze con casella di ricerca in linea
  • Risultati: visualizzazione delle abilità incluso l'elenco degli sviluppatori

Per ogni sviluppatore, visualizzeremo il nome, la foto, una breve descrizione e un elenco di abilità (ogni abilità si collegherà alla visualizzazione abilità corrispondente).

(Nota: i collegamenti a un'istanza di lavoro online dell'applicazione e al repository del codice sorgente sono entrambi forniti alla fine di questo articolo.)

Per mantenere il nostro focus primario sul framework Ractive, adotteremo una serie di semplificazioni che normalmente non dovrebbero essere fatte in produzione:

  • Tema predefinito. Utilizzeremo Bootstrap con il tema predefinito per lo stile, anziché personalizzare il tema per adattarlo allo stile dell'app.
  • Dipendenze. Aggiungeremo le nostre dipendenze come script separati che definiscono le variabili globali (piuttosto che utilizzare moduli ES6 o CommonJS o AMD con un caricatore appropriato per lo sviluppo e il passaggio di compilazione per la produzione).
  • Dati statici. Useremo i dati statici che ho preparato raschiando le pagine pubbliche del sito Toptal.
  • Nessun routing lato client. Ciò significa che l'URL rimarrà lo stesso quando passiamo da una visualizzazione all'altra. Non dovresti assolutamente farlo per le SPA, anche se potrebbe essere OK per alcuni piccoli componenti interattivi. Ractive non ha un'implementazione router integrata, ma può essere utilizzato con router di terze parti, come mostrato in questo esempio.
  • Modelli definiti all'interno di tag di script in HTML. Questa non è necessariamente una cattiva idea, soprattutto per le piccole applicazioni, e presenta alcuni vantaggi (è semplice e puoi elaborare questi modelli lato client insieme ai modelli lato server, ad esempio per l'internazionalizzazione). Ma per app più grandi potresti trarre vantaggio dalla precompilazione (ovvero, pre-analisi dei modelli per la rappresentazione JS interna.

Iniziamo con le app Web

OK, quindi, detto questo, iniziamo a creare l'app. Lo faremo in modo iterativo, aggiungendo funzionalità più piccole una per una ed esplorando i concetti man mano che li incontriamo.

Iniziamo creando una cartella con due file all'interno: index.html e script.js . La nostra app sarà estremamente semplice e funzionerà dal protocollo file:// in modo da evitare la necessità di avviare il server di sviluppo (anche se puoi, se lo desideri).

La pagina di ricerca

Inizieremo implementando la pagina di ricerca in cui l'utente può selezionare una competenza per la quale trovare sviluppatori corrispondenti nel database di Toptal.

Scheletro HTML

Iniziamo con questa banale pagina HTML:

 <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>

Come puoi vedere, è un banale documento HTML5. Carica Bootstrap dalla CDN, Lodash (una fantastica libreria di manipolazione dei dati) e Ractive.js.

Ractive non richiede di dedicare l'intera pagina alla SPA, quindi possiamo avere dei contenuti statici. Nel nostro caso, questo è costituito da un elemento contenitore e dal titolo della pagina.

Infine, carichiamo i dati che ho preparato per la demo e lo script che conterrà il nostro programma.

OK, ora che il nostro scheletro HTML è a posto, iniziamo ad aggiungere alcune funzionalità reali.

Elenco delle abilità

Una delle cose che mi piace particolarmente di Ractive è il modo in cui ti insegna a pensare alla rappresentazione finale (HTML) che vuoi ottenere, e poi ti consente di concentrarti sulla scrittura dei bit di codice necessari affinché ciò accada.

Quindi, per prima cosa, costruiamo un elenco di abilità come vista iniziale. Fare ciò comporta semplicemente:

  • Aggiunta di un elemento HTML in cui verrà visualizzato l'elenco delle abilità.
  • Aggiunta di un piccolo frammento di codice del modello al nostro HTML.
  • Scrivendo del JavaScript breve e semplice che fornisca i dati al template, per renderli nell'elemento HTML che abbiamo aggiunto.

Le modifiche all'HTML consistono in quanto segue:

 <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>

Non esiste una convenzione speciale con Ractive per specificare l'elemento HTML per ricevere i dati da visualizzare, ma il modo più semplice per farlo è aggiungere un ID all'elemento. Di solito uso l'ID "root" per questo scopo. Vedremo presto come viene utilizzato quando viene inizializzato Ractive. Per i curiosi ci sono altri modi per specificare l'elemento radice.

L'elemento di script leggermente imbarazzante con type="text/html" è un trucco intelligente per caricare un pezzo di HTML dal browser senza che venga analizzato o visualizzato, poiché i browser ignorano gli script di tipo sconosciuto. Il contenuto dello script è un modello simile a baffi/manubri (sebbene Ractive abbia alcune estensioni).

Per prima cosa scriviamo il codice del modello supponendo di avere accesso all'array delle abilità. Usiamo la direttiva mustache {{#each}} per definire l'iterazione. All'interno della direttiva, è possibile accedere all'elemento corrente come this . Di nuovo, assumiamo che la variabile skill contenga un array di stringhe, quindi la rendiamo semplicemente con un baffi di interpolazione {{this}} .

OK, questo è l'HTML. Ma per quanto riguarda JavaScript? Ecco dove avviene la “magia” che fornisce i dati al template::

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

Impressionante, no? In sole 10 righe di codice siamo in grado di:

  1. “Recupera” i dati dal “DB”.
  2. Crea un'istanza di una nuova app Ractive.
  3. Digli di eseguire il rendering all'interno dell'elemento con .
  4. Digli di usare un elemento di script con per ottenere il modello (ci sono anche altri modi per farlo).
  5. Passa i dati iniziali (vedremo come cambiarli in fase di esecuzione) o "ambito" se sei abituato alla terminologia angolare.
  6. Usa il metodo delle keys lodash per ottenere i nomi delle abilità che usiamo come chiavi oggetto nel "DB".

Quindi fondamentalmente con questo script diciamo al framework cosa fare, ma non come farlo. Il modello dichiara come, cosa che personalmente trovo piuttosto sorprendente e naturale.

Speriamo che tu stia iniziando a farti un'idea, quindi ora implementiamo qualcosa di più utile in aggiunta a quello che abbiamo.

Ricerca delle competenze

La pagina di ricerca, ovviamente, necessita di un campo di ricerca. E vorremmo che fornisse una funzionalità interattiva in base alla quale mentre l'utente digita nella casella di ricerca, l'elenco delle competenze viene filtrato per includere solo quelle che contengono la sottostringa immessa (con il filtro senza distinzione tra maiuscole e minuscole).

Come di consueto con Ractive, iniziamo con la definizione del template (pensando a quali nuove variabili di contesto saranno necessarie e cosa cambierebbe per quanto riguarda la gestione dei dati):

 <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>

Non così tanti cambiamenti, ma ancora una discreta quantità da imparare.

Innanzitutto, abbiamo aggiunto un nuovo <div> contenente la nostra casella di ricerca. È abbastanza ovvio che vogliamo connettere quell'input a qualche variabile (a meno che tu non abbia nostalgia dei bei vecchi tempi della zuppa jQuery). Ractive supporta il cosiddetto binding bidirezionale, il che significa che il tuo codice JS può recuperare un valore senza doverlo leggere manualmente dal DOM. Nel nostro caso, ciò si ottiene utilizzando l'interpolazione mustache value="{{ skillFilter }}" . Ractive comprende che vogliamo associare questa variabile all'attributo value dell'input. Quindi controlla l'input per noi e aggiorna automaticamente la variabile. Abbastanza pulito con solo 1 riga di HTML.

In secondo luogo, come spiegato nel commento nello snippet di codice sopra, ora invece di visualizzare tutte le abilità, creeremo una funzione JS skills() che filtrerà l'elenco delle abilità e restituirà solo quelle che corrispondono al testo inserito dall'utente:

 // 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); }); } } });

Sebbene sia pulito e semplice da implementare, potresti chiederti in che modo influisca sulle prestazioni. Voglio dire, chiameremo una funzione ogni volta? Bene, ogni volta cosa? Ractive è abbastanza intelligente da renderizzare nuovamente parti del modello (e chiamare qualsiasi funzione da esse) quando le loro dipendenze (variabili) cambiano (Ractive sa quando ciò accade grazie all'uso dei setter).

Per inciso, per coloro che sono interessati a fare un ulteriore passo avanti, c'è anche un modo più elegante per farlo usando una proprietà calcolata, ma lascerò che tu possa giocarci da solo, se lo desideri.

La pagina dei risultati

Ora che abbiamo un elenco di abilità ricercabile abbastanza utilizzabile, passiamo alla vista dei risultati in cui verrà visualizzato l'elenco corrispondente degli sviluppatori.

Passaggio da e verso la vista abilità

Ci sono ovviamente diversi modi in cui questo potrebbe essere implementato. Ho selezionato l'approccio di avere due punti di vista diversi a seconda che un'abilità sia stata selezionata o meno. In tal caso, mostriamo l'elenco degli sviluppatori corrispondenti; in caso contrario, mostriamo l'elenco delle abilità e la casella di ricerca.

Quindi, per cominciare, quando l'utente seleziona (cioè fa clic su) un nome di abilità, l'elenco delle abilità deve essere nascosto e il nome dell'abilità dovrebbe essere mostrato invece come intestazione della pagina. Al contrario, nella vista abilità selezionata, deve esserci un modo per chiudere quella vista e tornare all'elenco delle abilità.

Ecco il nostro primo passo lungo questo percorso:

 <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, stanno succedendo MOLTE cose qui.

Innanzitutto, per adattarlo all'implementazione come due viste diverse, ho spostato tutto ciò che avevamo fino ad ora (cioè la vista elenco) in qualcosa chiamato parziale. Un parziale è essenzialmente un pezzo di codice del modello che includeremo in un posto diverso (presto).

Quindi, vogliamo rendere le nostre abilità selezionabili e, quando viene fatto clic, vogliamo passare alla visualizzazione delle abilità corrispondente. Per questo, utilizziamo qualcosa chiamato eventi proxy, per cui reagiamo a un evento fisico (al clic, il nome è quello comprensibile da Ractive) e lo proxy all'evento logico (select-skill, il nome è come lo chiamiamo ) passando l'argomento (come probabilmente ricorderete questo sta per il nome dell'abilità qui).

(Cordiali saluti, esiste una sintassi alternativa di chiamate di metodo per ottenere la stessa cosa.)

Successivamente, assumiamo (di nuovo) di avere una variabile chiamata currentSkill che avrà il nome dell'abilità selezionata (se presente) o sarà vuota se non viene selezionata alcuna abilità. Quindi definiamo un altro parziale che mostra il nome dell'abilità corrente e ha anche un collegamento "CHIUDI" che dovrebbe deselezionare l'abilità.

Per JavaScript, l'aggiunta principale è il codice per iscriversi agli eventi select-skill e deselect-skill, aggiornando currentSkill (e skillFilter ) di conseguenza:

 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 });

Elenco degli sviluppatori per ogni abilità

Dopo aver preparato la nuova vista per l'abilità, ora possiamo aggiungere un po' di carne: l'elenco effettivo di sviluppatori che abbiamo per quell'elenco. Per questo, espandiamo il parziale per questa vista come segue:

 {{#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}}

Si spera che a questo punto tu abbia un'idea di cosa sta succedendo qui: abbiamo aggiunto una nuova sezione di iterazione al nostro parziale di skillView che itera sul risultato di una nuova funzione di skillDevelopers che scriveremo subito dopo. Per ogni sviluppatore nell'array (restituito da quella funzione skillDevelopers ), eseguiamo il rendering di un pannello e mostriamo il nome dello sviluppatore. Nota che potrei usare la forma implicita {{name}} qui e Ractive troverebbe l'attributo corretto cercando nella catena del contesto a partire dal contesto corrente (che nel nostro caso è l'oggetto sviluppatore vincolato da {{#each}} ), ma Preferisco essere esplicito. Maggiori informazioni su contesti e riferimenti sono disponibili nella documentazione Ractive.

Ed ecco l'implementazione della funzione 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]; }); }

Ampliare la voce per ogni sviluppatore

Ora che abbiamo un elenco di sviluppatori funzionante, è il momento di aggiungere ulteriori dettagli e ovviamente una bella foto:

 {{#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}}

Niente di nuovo qui dal lato Ractive delle cose, ma un uso un po' più pesante delle funzionalità di Bootstrap.

Visualizzazione di un elenco cliccabile di competenze dello sviluppatore

Finora abbiamo fatto buoni progressi, ma una caratteristica che ancora manca è l'altro lato della relazione tra sviluppatore di abilità; in particolare, vogliamo mostrare le abilità di ogni sviluppatore e vogliamo che ciascuna di queste abilità sia un collegamento cliccabile che ci porti alla visualizzazione dei risultati per quella abilità.

Ma aspetta... sono sicuro che abbiamo già esattamente la stessa cosa nell'elenco delle abilità. Sì, in effetti, lo facciamo. È nell'elenco cliccabile delle abilità, ma proviene da una matrice diversa rispetto al set di abilità di ogni sviluppatore. Eppure questi sono sufficientemente simili che è un chiaro segno per me che dovremmo riutilizzare quel pezzo di HTML. E a tal fine, i parziali sono nostri amici.

(Nota: Ractive ha anche un approccio più avanzato per i blocchi riutilizzabili di una vista, noti come componenti. Sono davvero molto utili, ma per semplicità, non li discuteremo ora.)

Quindi ecco come riusciamo a farlo usando i parziali (e notiamo, per inciso, che siamo in grado di aggiungere questa funzionalità senza aggiungere una singola riga di codice 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}}

Ho già l'elenco delle abilità allegato all'oggetto dello sviluppatore che abbiamo recuperato dal "DB", quindi ho solo modificato un po' il modello: ho spostato la riga che rende l'etichetta della competenza su un parziale e ho usato questo parziale dove era originariamente quella riga.

Quindi, quando ripeto le abilità dello sviluppatore, posso riutilizzare questo stesso nuovo parziale per visualizzare ciascuna di queste abilità anche come collegamento cliccabile. Inoltre, questo proxy anche l'evento di selezione dell'abilità, se ricordi, passando lo stesso nome dell'abilità. Ciò significa che possiamo includerlo ovunque (avendo il contesto appropriato) e otterremo un'etichetta cliccabile che porta alla visualizzazione delle abilità!

Tocco finale — Precaricatore

OK, ora abbiamo un'app funzionale di base. È pulito e funziona velocemente, ma ci vuole ancora del tempo per caricarsi. (Nel nostro caso, ciò è in parte dovuto al fatto che utilizziamo fonti non concatenate e non minimizzate, ma in un'app del mondo reale possono esserci altri motivi significativi, come il caricamento dei dati iniziali).

Quindi, come passaggio finale, ti mostrerò un trucco accurato per aggiungere un'animazione di precaricamento che verrà rimossa non appena Ractive eseguirà il rendering della nostra app:

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

Allora qual è la magia qui? In realtà è abbastanza semplice. Ho aggiunto del contenuto (è una barra di avanzamento animata Bootstrap, ma potrebbe essere una GIF animata o altro) direttamente al nostro elemento radice. Penso che sia piuttosto intelligente: mentre i nostri script vengono caricati, l'utente vede l'indicatore di caricamento (poiché non ha alcuna dipendenza da JavaScript, può essere visualizzato immediatamente). Tuttavia, non appena l'app Ractive viene inizializzata, Ractive sovrascriverà il contenuto dell'elemento radice (e quindi cancellerà l'animazione di precaricamento) con il modello renderizzato. In questo modo, siamo in grado di ottenere questo effetto solo con un pezzo di HTML statico e 0 righe di logica. Penso che sia abbastanza bello.

Conclusione

Pensa a ciò che abbiamo realizzato qui e alla facilità con cui lo abbiamo realizzato. Abbiamo un'app piuttosto completa: mostra un elenco di abilità, consente di cercarle rapidamente (e supporta persino l'aggiornamento interattivo dell'elenco delle abilità mentre l'utente digita nella casella di ricerca), consente di navigare verso una particolare abilità e tornare indietro ed elenca gli sviluppatori per ogni abilità selezionata. Inoltre, possiamo fare clic su qualsiasi abilità elencata da qualsiasi sviluppatore per portarci all'elenco degli sviluppatori con tale abilità. E tutto questo con meno di 80 righe di HTML e meno di 40 righe di JavaScript. A mio avviso, è piuttosto impressionante e la dice lunga sulla potenza, l'eleganza e la semplicità di Ractive.

Una versione funzionante dell'app è disponibile online qui e il codice sorgente completo è pubblico e disponibile qui.

Ovviamente, in questo articolo abbiamo appena scalfito la superficie di ciò che è possibile fare con il framework Ractive. Se ti piace quello che hai visto finora, ti consiglio vivamente di iniziare con la configurazione di 60 secondi di Ractive e iniziare a esplorare da solo tutto ciò che Ractive ha da offrire.