Ractive.js - Aplicativos da Web facilitados
Publicados: 2022-03-11No cenário atual de rápida proliferação de estruturas e bibliotecas JavaScript, selecionar aquela na qual você deseja basear seu desenvolvimento pode ser um grande desafio. Afinal, uma vez que você segue o caminho de usar uma estrutura específica, migrar seu código para usar uma diferente é uma tarefa não trivial que você pode nunca ter tempo ou orçamento para executar.
Então, por que Ractive.js?
Ao contrário de outras ferramentas que geram HTML inerte, o Ractive transforma modelos em projetos para aplicativos interativos por padrão. E embora se possa certamente argumentar que a contribuição de Ractive é mais evolucionária do que revolucionária, seu valor é significativo.
O que torna o Ractive tão útil é que ele fornece recursos poderosos, mas o faz de uma maneira que é agradavelmente simples para o desenvolvedor usar. Além disso, é bastante elegante, rápido, discreto e pequeno.
Neste artigo, abordaremos o processo de criação de um aplicativo de pesquisa Ractive simples, demonstrando alguns dos principais recursos do Ractive e as maneiras como ele ajuda a simplificar o desenvolvimento e aplicativos da Web.
O que é Ractive.js?
O Ractive foi originalmente criado para resolver o problema de vinculação de dados de uma maneira mais elegante. Para isso, ele pega modelos e os transforma em uma representação virtual leve do DOM para que, quando os dados forem alterados, o DOM real seja atualizado de forma inteligente e eficiente.
Mas logo ficou claro que a abordagem e a infraestrutura empregadas pela Ractive também poderiam ser usadas para fazer outras coisas com mais eficiência. Ele pode, por exemplo, cuidar automaticamente de coisas como reutilizar manipuladores de eventos e desvinculá-los automaticamente quando não forem mais necessários. A delegação de eventos torna-se desnecessária. Assim como na vinculação de dados, essa abordagem evita que o código se torne pesado à medida que um aplicativo cresce.
Os principais recursos, como ligação bidirecional, animações e suporte a SVG, são fornecidos prontos para uso, e a funcionalidade personalizada pode ser facilmente adicionada por meio de plug-ins.
Enquanto algumas ferramentas e frameworks forçam você a aprender um novo vocabulário e estruturar seu aplicativo de uma maneira particular, o Ractive funciona para você, e não o contrário. Também se integra bem com outras bibliotecas.
Nosso aplicativo de amostra
Nosso aplicativo de amostra será usado para pesquisar o banco de dados Toptal de desenvolvedores com base em habilidades. Nosso aplicativo terá duas visualizações:
- Pesquisa: lista de habilidades com caixa de pesquisa em linha
- Resultados: visualização de habilidades incluindo lista de desenvolvedores
Para cada desenvolvedor, exibiremos seu nome, foto, breve descrição e uma lista de habilidades (cada habilidade será vinculada à visualização de habilidades correspondente).
(Observação: links para uma instância de trabalho online do aplicativo e o repositório de código-fonte são fornecidos no final deste artigo.)
Para manter nosso foco principal no framework Ractive, empregaremos uma série de simplificações que normalmente não deveriam ser feitas em produção:
- Tema Padrão. Usaremos o Bootstrap com o tema padrão para estilo, em vez de personalizar o tema para se adequar ao estilo do seu aplicativo.
- Dependências. Adicionaremos nossas dependências como scripts separados que definem variáveis globais (em vez de usar módulos ES6, CommonJS ou AMD com carregador adequado para desenvolvimento e a etapa de construção para produção).
- Dados estáticos. Usaremos dados estáticos que preparei raspando as páginas públicas no site da Toptal.
- Sem roteamento do lado do cliente. Isso significa que a URL permanecerá a mesma enquanto alternamos entre as visualizações. Você definitivamente não deve fazer isso para SPAs, embora possa ser bom para alguns pequenos componentes interativos. O Ractive não possui uma implementação de roteador integrada, mas pode ser usado com roteadores de terceiros, conforme mostrado neste exemplo.
- Modelos definidos dentro de tags de script em HTML. Isso não é necessariamente uma má ideia, especialmente para aplicativos pequenos, e tem algumas vantagens (é simples, e você pode processar esses modelos do lado do cliente junto com seus modelos do lado do servidor, por exemplo, para internacionalização). Mas para aplicativos maiores, você pode se beneficiar da pré-compilação (também conhecida como modelos de pré-análise para representação JS interna.
Vamos começar com aplicativos da Web
OK, então com isso dito, vamos começar a construir o aplicativo. Faremos isso de maneira iterativa, adicionando recursos menores um por um e explorando os conceitos à medida que os encontramos.
Vamos começar criando uma pasta com dois arquivos dentro: index.html
e script.js
. Nosso aplicativo será extremamente simples e funcionará a partir do protocolo file://
para evitar a necessidade de iniciar o servidor de desenvolvimento (embora você possa, se desejar).
A página de pesquisa
Começaremos implementando a página de pesquisa onde o usuário pode selecionar uma habilidade para encontrar desenvolvedores correspondentes no banco de dados Toptal.
Esqueleto HTML
Vamos começar com esta página HTML trivial:
<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>
Como você pode ver, é um documento HTML5 trivial. Ele carrega Bootstrap do CDN, Lodash (uma biblioteca de manipulação de dados incrível) e Ractive.js.
Ractive não requer dedicar a página inteira ao SPA, então podemos ter algum conteúdo estático. No nosso caso, isso consiste em um elemento container e no título da página.
Por fim, carregamos os dados que preparei para a demonstração e o script que conterá nosso programa.
OK, agora que nosso esqueleto HTML está pronto, vamos começar a adicionar algumas funcionalidades reais.
Lista de Habilidades
Uma das coisas que eu particularmente gosto no Ractive é como ele ensina você a pensar sobre a representação final (HTML) que você deseja alcançar e, em seguida, permite que você se concentre em escrever os bits de código necessários para que isso aconteça.
Então, primeiro, vamos construir uma lista de habilidades como nossa visão inicial. Fazer isso implica simplesmente:
- Adicionando um elemento HTML no qual a lista de habilidades será exibida.
- Adicionando um pequeno trecho de código de modelo ao nosso HTML.
- Escrevendo algum JavaScript breve e simples que forneça os dados ao modelo, para renderizá-lo no elemento HTML que adicionamos.
Os mods para o HTML consistem no seguinte:
<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>
Não há nenhuma convenção especial com o Ractive para especificar o elemento HTML para receber os dados a serem exibidos, mas a maneira mais simples de fazer isso é adicionar um ID ao elemento. Eu costumo usar o ID “root” para esta finalidade. Veremos em breve como ele é usado quando o Ractive é inicializado. Para os curiosos, existem outras maneiras de especificar o elemento raiz.
O elemento script um pouco estranho com type="text/html"
é um truque inteligente para obter um pedaço de HTML carregado pelo navegador sem que ele seja analisado ou renderizado, pois os navegadores ignoram scripts de tipo desconhecido. O conteúdo do script é um modelo do tipo Mustache/Handlebars (embora o Ractive tenha algumas extensões).
Primeiro escrevemos o código do modelo assumindo que temos acesso ao array de habilidades. Usamos a diretiva bigode {{#each}}
para definir a iteração. Dentro da diretiva, o elemento atual pode ser acessado como this
. Novamente, assumimos que a variável skills contém um array de strings, então nós simplesmente a renderizamos com um bigode de interpolação {{this}}
.
OK, esse é o HTML. Mas e o JavaScript? É aí que acontece a “mágica” que fornece os dados para o template::
(function () { var skills = DB.skills, developers = DB.developers; var app = new Ractive({ el: '#root', template: '#tpl-app', data: { skills: _.keys(DB.skills) } }); }());
Impressionante, não? Em apenas 10 linhas de código, somos capazes de:
- “Recuperar” os dados do “DB”.
- Instancie um novo aplicativo Ractive.
- Diga-lhe para renderizar dentro do elemento com
.
- Diga a ele para usar um elemento de script com
para obter o modelo (há outras maneiras de fazer isso também).
- Passe os dados iniciais (veremos como alterá-los em tempo de execução), ou “escopo” se você estiver acostumado com a terminologia Angular.
- Use o método lodash
keys
para obter os nomes das habilidades que usamos como chaves de objeto no “DB”.
Então, basicamente, com este script, dizemos ao framework o que fazer, mas não como fazê-lo. O modelo declara como, o que eu pessoalmente acho incrível e natural.
Espero que você esteja começando a entender a ideia, então agora vamos implementar algo mais útil em cima do que temos.
Pesquisa de habilidades
A página de pesquisa, é claro, precisa de um campo de pesquisa. E gostaríamos que ele fornecesse um recurso interativo pelo qual, à medida que o usuário digita na caixa de pesquisa, a lista de habilidades é filtrada, incluindo apenas aquelas que contêm a substring inserida (com a filtragem não diferenciando maiúsculas de minúsculas).
Como de costume com o Ractive, começamos definindo o modelo (enquanto pensamos quais novas variáveis de contexto serão necessárias e o que mudaria em relação ao gerenciamento de dados):
<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>
Não tantas mudanças, mas ainda uma quantidade razoável para aprender.
Primeiro, adicionamos um novo <div> contendo nossa caixa de pesquisa. É bastante óbvio que queremos conectar essa entrada a alguma variável (a menos que você esteja nostálgico sobre os bons e velhos dias de sopa do jQuery). O Ractive suporta a chamada ligação bidirecional, o que significa que seu código JS pode recuperar um valor sem precisar lê-lo manualmente do DOM. No nosso caso, isso é feito usando a interpolação bigode value="{{ skillFilter }}"
. O Ractive entende que queremos vincular essa variável ao atributo value da entrada. Então, ele observa a entrada para nós e atualiza automaticamente a variável. Muito legal com apenas 1 linha de HTML.
Segundo, conforme explicado no comentário no trecho de código acima, agora ao invés de exibir todas as habilidades, vamos criar uma função JS skills()
que filtrará a lista de habilidades e retornará apenas aquelas que corresponderem ao texto digitado pelo usuário:
// 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); }); } } });
Embora isso seja limpo e simples de implementar, você pode estar se perguntando como isso afeta o desempenho. Quero dizer, vamos chamar uma função a cada vez? Bem, cada vez o que? Ractive é inteligente o suficiente para apenas renderizar novamente partes do template (e chamar qualquer função delas) quando suas dependências (variáveis) mudam (Ractive sabe quando isso acontece graças ao uso de setters).

Aliás, para aqueles interessados em levar isso um passo adiante, também há uma maneira mais elegante de fazer isso usando uma propriedade computada, mas vou deixar isso para você brincar sozinho, se quiser.
A página de resultados
Agora que temos uma lista de habilidades pesquisáveis bastante utilizável, vamos passar para a visualização de resultados, onde a lista correspondente de desenvolvedores será exibida.
Mudando de e para a Exibição de Habilidade
Obviamente, existem várias maneiras de implementar isso. Eu selecionei a abordagem de haver duas visões diferentes dependendo se uma habilidade foi ou não selecionada. Em caso afirmativo, mostramos a lista de desenvolvedores correspondentes; caso contrário, mostramos a lista de habilidades e a caixa de pesquisa.
Portanto, para começar, quando o usuário seleciona (ou seja, clica em) um nome de habilidade, a lista de habilidades precisa ser ocultada e o nome da habilidade deve ser mostrado como o título da página. Por outro lado, na visualização de habilidades selecionadas, deve haver uma maneira de fechar essa visualização e voltar à lista de habilidades.
Aqui está o nosso primeiro passo neste caminho:
<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">× 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, há muita coisa acontecendo aqui.
Primeiro, para acomodar a implementação disso como duas visualizações diferentes, mudei tudo o que tínhamos até agora (ou seja, a visualização de lista) para algo chamado parcial. Um parcial é essencialmente um pedaço de código de modelo que vamos incluir em um lugar diferente (em breve).
Em seguida, queremos tornar nossas habilidades clicáveis e, quando clicadas, queremos navegar para a visualização de habilidades correspondente. Para isso, usamos algo chamado eventos proxy, onde reagimos a um evento físico (no clique, o nome é o que Ractive entende) e o fazemos proxy para o evento lógico (selecionar habilidade, o nome é o que chamamos ) passando o argumento (como você provavelmente se lembra, isso significa o nome da habilidade aqui).
(Para sua informação, existe uma sintaxe alternativa de chamadas de método para realizar a mesma coisa.)
Em seguida, assumimos (novamente) que teremos uma variável chamada currentSkill
que terá o nome da habilidade selecionada (se houver), ou estará vazia se nenhuma habilidade for selecionada. Então definimos outra parcial que mostra o nome da habilidade atual, e também tem um link “CLOSE” que deve desmarcar a habilidade.
Para o JavaScript, a principal adição é o código para assinar os eventos select-skill e deselect-skill, atualizando currentSkill
(e skillFilter
) de acordo:
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 });
Listando desenvolvedores para cada habilidade
Tendo preparado a nova visão para a habilidade, agora podemos adicionar um pouco de carne - a lista real de desenvolvedores que temos para essa lista. Para isso, expandimos a parcial para essa visão da seguinte forma:
{{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">× CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body"> {{ this.name }} </div> </div> {{/each}} {{/partial}}
Espero que, a essa altura, você esteja entendendo o que está acontecendo aqui: adicionamos uma nova seção de iteração à nossa parcial skillView
que itera sobre o resultado de uma nova função skillDevelopers
que escreveremos a seguir. Para cada desenvolvedor no array (retornado por essa função skillDevelopers
), renderizamos um painel e exibimos o nome do desenvolvedor. Observe que eu poderia usar a forma implícita {{name}}
aqui e o Ractive encontraria o atributo apropriado pesquisando a cadeia de contexto a partir do contexto atual (que no nosso caso é o objeto do desenvolvedor vinculado por {{#each}}
), mas Prefiro ser explícito. Mais informações sobre contextos e referências estão disponíveis na documentação do Ractive.
E aqui está a implementação da função 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]; }); }
Expandindo a entrada para cada desenvolvedor
Agora que temos uma lista de desenvolvedores funcionando, é hora de adicionar mais detalhes e uma bela foto, é claro:
{{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">× 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}}
Nada de novo aqui do lado Ractive das coisas, mas um uso um pouco mais pesado dos recursos do Bootstrap.
Exibindo uma lista clicável de habilidades de desenvolvedor
Fizemos um bom progresso até agora, mas um recurso que ainda está faltando é o outro lado da relação desenvolvedor de habilidades; ou seja, queremos exibir as habilidades de cada desenvolvedor e queremos que cada uma dessas habilidades seja um link clicável que nos leve à visualização de resultados dessa habilidade.
Mas espere... Tenho certeza de que já temos exatamente a mesma coisa na lista de habilidades. Sim, de fato, temos. Está na lista clicável de habilidades, mas vem de uma matriz diferente do conjunto de habilidades de cada desenvolvedor. No entanto, eles são suficientemente semelhantes para que seja um sinal claro para mim de que devemos reutilizar esse pedaço de HTML. E nesse sentido, parciais são nossos amigos.
(Nota: Ractive também tem uma abordagem mais avançada para pedaços reutilizáveis de uma visão, conhecidos como componentes. Eles são realmente muito úteis, mas por uma questão de simplicidade, não vamos discuti-los agora.)
Então, aqui está como fazemos isso usando parciais (e observe, aliás, que podemos adicionar essa funcionalidade sem adicionar uma única linha de código 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">× 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}} {{/each}} </p> </div> </div> </div> {{/each}} {{/partial}}
Já tenho a lista de habilidades anexada ao objeto do desenvolvedor que recuperamos do “DB”, então apenas alterei um pouco o template: movi a linha que renderiza o rótulo da habilidade para uma parcial e usei essa parcial onde essa linha estava originalmente.
Então, quando eu iterar sobre as habilidades do desenvolvedor, posso reutilizar essa mesma nova parcial para exibir cada uma dessas habilidades também como um link clicável. Além disso, isso também representa o evento select-skill, se você se lembrar, passando o mesmo nome da habilidade. Isso significa que podemos incluir isso em qualquer lugar (com o contexto adequado) e obteremos um rótulo clicável que leva à visualização da habilidade!
Toque Final - Pré-carregador
OK, agora temos um aplicativo funcional básico. É limpo e funciona rápido, mas ainda leva algum tempo para carregar. (No nosso caso, isso se deve parcialmente ao fato de usarmos fontes não concatenadas e não minificadas, mas em um aplicativo do mundo real pode haver outros motivos significativos, como o carregamento de dados iniciais).
Então, como uma etapa final, mostrarei um truque legal para adicionar uma animação de pré-carregamento que será removida assim que o Ractive renderizar nosso aplicativo:
<div class="container"> <h1>Toptal Search</h1> <div> <div class="progress"> <div class="progress-bar progress-bar-striped active"> Loading... </div> </div> </div> </div>
Então, qual é a mágica aqui? Na verdade é bem simples. Eu adicionei algum conteúdo (é uma barra de progresso animada do Bootstrap, mas pode ser um GIF animado, ou qualquer outra coisa) diretamente ao nosso elemento raiz. Acho bem inteligente — enquanto nossos scripts estão carregando, o usuário vê o indicador de carregamento (já que não tem nenhuma dependência do JavaScript, pode ser exibido imediatamente). No entanto, assim que o aplicativo Ractive for inicializado, o Ractive substituirá o conteúdo do elemento raiz (e, assim, apagará a animação de pré-carregamento) pelo modelo renderizado. Dessa forma, conseguimos obter esse efeito apenas com um pedaço de HTML estático e 0 linhas de lógica. Eu acho isso muito legal.
Conclusão
Pense no que realizamos aqui e na facilidade com que o realizamos. Temos um aplicativo bastante completo: ele mostra uma lista de habilidades, permite pesquisá-las rapidamente (e ainda suporta atualização interativa da lista de habilidades à medida que o usuário digita na caixa de pesquisa), permite navegar para uma determinada habilidade e voltar e lista os desenvolvedores para cada habilidade selecionada. Além disso, podemos clicar em qualquer habilidade listada por qualquer desenvolvedor para nos levar à lista de desenvolvedores com essa habilidade. E tudo isso com menos de 80 linhas de HTML e menos de 40 linhas de JavaScript. Na minha opinião, isso é bastante impressionante e fala muito sobre o poder, a elegância e a simplicidade do Ractive.
Uma versão funcional do aplicativo está disponível online aqui e o código-fonte completo é público e disponível aqui.
Claro, nós apenas arranhamos a superfície neste artigo do que é possível com o framework Ractive. Se você gostou do que viu até agora, recomendo fortemente que você comece com a configuração de 60 segundos do Ractive e comece a explorar por si mesmo tudo o que o Ractive tem a oferecer.