Ractive.js - Aplicaciones web simplificadas

Publicado: 2022-03-11

En el panorama actual de rápida proliferación de marcos y bibliotecas de JavaScript, seleccionar el que desea basar su desarrollo puede ser todo un desafío. Después de todo, una vez que toma el camino de usar un marco en particular, migrar su código para usar uno diferente es una tarea no trivial que quizás nunca tenga el tiempo o el presupuesto para realizar.

Entonces, ¿por qué Ractive.js?

A diferencia de otras herramientas que generan HTML inerte, Ractive transforma plantillas en planos para aplicaciones que son interactivas de forma predeterminada. Y aunque ciertamente se podría argumentar que la contribución de Ractive es más evolutiva que revolucionaria, su valor es significativo.

Lo que hace que Ractive sea tan útil es que brinda capacidades poderosas, pero lo hace de una manera que es sorprendentemente simple de usar para el desarrollador. Además, es bastante elegante, rápido, discreto y pequeño.

En este artículo, repasaremos el proceso de creación de una aplicación de búsqueda Ractive simple, demostrando algunas de las funciones clave de Ractive y las formas en que ayuda a simplificar el desarrollo y las aplicaciones web.

Ractive.js y aplicaciones web

¿Qué es Ractive.js?

Ractive se creó originalmente para abordar el problema del enlace de datos de una manera más elegante. Con ese fin, toma plantillas y las transforma en una representación virtual liviana del DOM para que, cuando los datos cambien, el DOM real se actualice de manera inteligente y eficiente.

Pero pronto se hizo evidente que el enfoque y la infraestructura empleados por Ractive también podrían usarse para hacer otras cosas de manera más eficiente. Puede, por ejemplo, ocuparse automáticamente de cosas como reutilizar controladores de eventos y desvincularlos automáticamente cuando ya no se necesiten. La delegación de eventos se vuelve innecesaria. Al igual que con el enlace de datos, este enfoque evita que el código se vuelva difícil de manejar a medida que crece la aplicación.

Las características clave, como el enlace bidireccional, las animaciones y la compatibilidad con SVG, se proporcionan listas para usar, y la funcionalidad personalizada se puede agregar fácilmente a través de complementos.

Mientras que algunas herramientas y marcos lo obligan a aprender un nuevo vocabulario y estructurar su aplicación de una manera particular, Ractive funciona para usted, no al revés. También se integra bien con otras bibliotecas.

Nuestra aplicación de muestra

Nuestra aplicación de muestra se utilizará para buscar en la base de datos de desarrolladores de Toptal según sus habilidades. Nuestra aplicación tendrá dos vistas:

  • Buscar: lista de habilidades con cuadro de búsqueda en línea
  • Resultados: vista de habilidades que incluye una lista de desarrolladores

Para cada desarrollador, mostraremos su nombre, foto, breve descripción y una lista de habilidades (cada habilidad se vinculará a la vista de habilidades correspondiente).

(Nota: los enlaces a una instancia de trabajo en línea de la aplicación y el repositorio del código fuente se proporcionan al final de este artículo).

Para mantener nuestro enfoque principal en el marco Ractive, emplearemos una serie de simplificaciones que normalmente no deberían realizarse en producción:

  • Tema predeterminado. Usaremos Bootstrap con el tema predeterminado para diseñar, en lugar de personalizar el tema para que se ajuste al estilo de su aplicación.
  • dependencias. Agregaremos nuestras dependencias como scripts separados que definen variables globales (en lugar de usar módulos ES6, CommonJS o AMD con el cargador adecuado para el desarrollo y el paso de compilación para la producción).
  • Datos estáticos. Usaremos datos estáticos que preparé raspando las páginas públicas en el sitio de Toptal.
  • Sin enrutamiento del lado del cliente. Esto significa que la URL permanecerá igual cuando cambiemos de vista. Definitivamente no debería hacer eso para los SPA, aunque puede estar bien para algunos pequeños componentes interactivos. Ractive no tiene una implementación de enrutador integrada, pero se puede usar con enrutadores de terceros, como se muestra en este ejemplo.
  • Plantillas definidas dentro de etiquetas de script en HTML. Esto no es necesariamente una mala idea, especialmente para aplicaciones pequeñas, y tiene algunas ventajas (es simple y puede procesar estas plantillas del lado del cliente junto con las plantillas del lado del servidor, por ejemplo, para la internacionalización). Pero para aplicaciones más grandes, podría beneficiarse de la compilación previa (también conocida como plantillas de análisis previo para la representación interna de JS).

Comencemos con las aplicaciones web

Bien, dicho esto, comencemos a construir la aplicación. Lo haremos de manera iterativa, agregando características más pequeñas una por una y explorando los conceptos a medida que los encontremos.

Comencemos por crear una carpeta con dos archivos dentro: index.html y script.js . Nuestra aplicación será extremadamente simple y funcionará desde el protocolo file:// para evitar la necesidad de iniciar el servidor de desarrollo (aunque puede hacerlo si lo desea).

La página de búsqueda

Comenzaremos implementando la página de búsqueda donde el usuario puede seleccionar una habilidad para encontrar desarrolladores coincidentes en la base de datos de Toptal.

Esqueleto HTML

Comencemos con 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 puede ver, es un documento HTML5 trivial. Carga Bootstrap desde la CDN, Lodash (una impresionante biblioteca de manipulación de datos) y Ractive.js.

Ractive no requiere dedicar toda la página a SPA, por lo que podemos tener algo de contenido estático. En nuestro caso, este consta de un elemento contenedor y el título de la página.

Finalmente, cargamos los datos que he preparado para la demo, y el script que contendrá nuestro programa.

Bien, ahora que nuestro esqueleto HTML está en su lugar, comencemos a agregar algunas funciones reales.

Lista de Habilidades

Una de las cosas que más me gustan de Ractive es cómo te enseña a pensar en la representación final (HTML) que quieres lograr y luego te permite concentrarte en escribir los fragmentos de código necesarios para que eso suceda.

Entonces, primero, construyamos una lista de habilidades como nuestra vista inicial. Hacer esto simplemente implica:

  • Agregar un elemento HTML en el que se mostrará la lista de habilidades.
  • Agregar un pequeño fragmento de código de plantilla a nuestro HTML.
  • Escribiendo un JavaScript breve y simple que suministre los datos a la plantilla, para representarlos en el elemento HTML que agregamos.

Las modificaciones al HTML consisten en lo siguiente:

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

No existe una convención especial con Ractive para especificar el elemento HTML para recibir los datos que se mostrarán, pero la forma más sencilla de hacerlo es agregar una ID al elemento. Usualmente uso la identificación "raíz" para este propósito. Veremos pronto cómo se usa cuando se inicializa Ractive. Para aquellos curiosos, hay otras formas de especificar el elemento raíz.

El elemento de secuencia de comandos ligeramente incómodo con type="text/html" es un truco inteligente para que el navegador cargue una parte de HTML sin que se analice o represente, ya que los navegadores ignoran las secuencias de comandos de tipo desconocido. El contenido del script es una plantilla tipo Moustache/Handlebars (aunque Ractive tiene algunas extensiones).

Primero escribimos el código de la plantilla asumiendo que tenemos acceso a la matriz de habilidades. Usamos la directiva {{#each}} para definir la iteración. Dentro de la directiva, se puede acceder al elemento actual this . Nuevamente, asumimos que la variable de habilidades contiene una matriz de cadenas, por lo que simplemente la representamos con un bigote de interpolación {{this}} .

Bien, ese es el HTML. Pero, ¿qué pasa con el JavaScript? Ahí es donde sucede la "magia" que proporciona los datos a la plantilla:

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

Impresionante, ¿no? En solo esas 10 líneas de código podemos:

  1. “Recuperar” los datos de la “BD”.
  2. Instanciar una nueva aplicación Ractive.
  3. Dígale que renderice dentro del elemento con .
  4. Dígale que use un elemento de secuencia de comandos con para obtener la plantilla (también hay otras formas de hacerlo).
  5. Pase los datos iniciales (veremos cómo cambiarlos en el tiempo de ejecución), o "ámbito" si está acostumbrado a la terminología angular.
  6. Use el método de las keys lodash para obtener los nombres de las habilidades que usamos como claves de objeto en la "BD".

Básicamente, con este script le decimos al marco qué hacer, pero no cómo hacerlo. La plantilla declara cómo, que personalmente encuentro bastante sorprendente y natural.

Esperemos que estés empezando a entender la idea, así que ahora implementemos algo más útil además de lo que tenemos.

Búsqueda de habilidades

La página de búsqueda, por supuesto, necesita un campo de búsqueda. Y nos gustaría que brinde una capacidad interactiva en la que, a medida que el usuario escribe en el cuadro de búsqueda, la lista de habilidades se filtra y solo incluye aquellas que contienen la subcadena ingresada (el filtrado no distingue entre mayúsculas y minúsculas).

Como es habitual con Ractive, comenzamos definiendo la plantilla (mientras pensamos qué nuevas variables de contexto se necesitarán y qué cambiaría con respecto a la gestión de datos):

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

No hay tantos cambios, pero aún queda mucho por aprender.

Primero, agregamos un nuevo <div> que contiene nuestro cuadro de búsqueda. Es bastante obvio que queremos conectar esa entrada a alguna variable (a menos que sienta nostalgia por los viejos tiempos de la sopa jQuery). Ractive admite el llamado enlace bidireccional, lo que significa que su código JS puede recuperar un valor sin necesidad de leerlo manualmente desde el DOM. En nuestro caso, esto se logra usando la interpolación value="{{ skillFilter }}" . Ractive entiende que queremos vincular esta variable al atributo de valor de la entrada. Así que observa la entrada por nosotros y actualiza automáticamente la variable. Bastante ordenado con solo 1 línea de HTML.

En segundo lugar, como se explica en el comentario del fragmento de código anterior, ahora en lugar de mostrar todas las habilidades, crearemos una función JS skills() que filtrará la lista de habilidades y solo devolverá aquellas que coincidan con el texto ingresado por el usuario:

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

Si bien esto es limpio y simple de implementar, es posible que se pregunte cómo afecta el rendimiento. Quiero decir, ¿vamos a llamar a una función cada vez? Bueno, ¿cada vez qué? Ractive es lo suficientemente inteligente como para volver a renderizar solo partes de la plantilla (y llamar a cualquier función desde ellas) cuando cambian sus dependencias (variables) (Ractive sabe cuándo sucede eso gracias al uso de setters).

Por cierto, para aquellos interesados ​​en llevar esto un paso más allá, también hay una forma más elegante de hacerlo utilizando una propiedad calculada, pero dejaré que jueguen con eso por su cuenta si lo desean.

La página de resultados

Ahora que tenemos una lista de habilidades de búsqueda bastante utilizable, pasemos a la vista de resultados donde se mostrará la lista coincidente de desarrolladores.

Cambiar a y desde la Vista de habilidades

Obviamente, hay múltiples formas en que esto podría implementarse. Seleccioné el enfoque de que haya dos vistas diferentes dependiendo de si se ha seleccionado o no una habilidad. Si es así, mostramos la lista de desarrolladores coincidentes; si no, mostramos la lista de habilidades y el cuadro de búsqueda.

Entonces, para empezar, cuando el usuario selecciona (es decir, hace clic en) un nombre de habilidad, la lista de habilidades debe ocultarse y el nombre de la habilidad debe mostrarse como el encabezado de la página. Por el contrario, en la vista de habilidades seleccionada, debe haber una forma de cerrar esa vista y volver a la lista de habilidades.

Este es nuestro primer paso en este camino:

 <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, están sucediendo MUCHAS cosas aquí.

Primero, para acomodar la implementación de esto como dos vistas diferentes, moví todo lo que teníamos hasta ahora (es decir, la vista de lista) a algo llamado parcial. Un parcial es esencialmente un trozo de código de plantilla que vamos a incluir en un lugar diferente (pronto).

Luego, queremos que se pueda hacer clic en nuestras habilidades, y cuando se haga clic en ellas, queremos navegar a la vista de habilidades correspondiente. Para esto, usamos algo llamado eventos proxy, mediante el cual reaccionamos a un evento físico (al hacer clic, el nombre es comprensible para Ractive) y lo delegamos al evento lógico (select-skill, el nombre es como lo llamemos ) pasando el argumento (como probablemente recuerde, esto representa el nombre de la habilidad aquí).

(Para su información, existe una sintaxis alternativa de llamadas a métodos para lograr lo mismo).

A continuación, asumimos (nuevamente) que tendremos una variable llamada currentSkill que tendrá el nombre de la habilidad seleccionada (si la hay), o estará vacía si no se selecciona ninguna habilidad. Así que definimos otro parcial que muestra el nombre de la habilidad actual y también tiene un enlace "CERRAR" que debería anular la selección de la habilidad.

Para JavaScript, la adición principal es el código para suscribirse a los eventos select-skill y deselect-skill, actualizando currentSkill (y skillFilter ) en consecuencia:

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

Listado de desarrolladores para cada habilidad

Habiendo preparado la nueva vista para la habilidad, ahora podemos agregar algo de carne: la lista real de desarrolladores que tenemos para esa lista. Para eso, expandimos el parcial para esta vista de la siguiente manera:

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

Con suerte, en este punto, ya tiene una idea de lo que está sucediendo aquí: hemos agregado una nueva sección de iteración a nuestro parcial skillView que itera sobre el resultado de una nueva función skillDevelopers que vamos a escribir a continuación. Para cada desarrollador en la matriz (devuelto por esa función skillDevelopers ), representamos un panel y mostramos el nombre del desarrollador. Tenga en cuenta que podría usar la forma implícita {{name}} aquí y Ractive encontraría el atributo adecuado buscando en la cadena de contexto a partir del contexto actual (que en nuestro caso es el objeto desarrollador vinculado por {{#each}} ), pero Prefiero ser explícito. Más información sobre contextos y referencias está disponible en la documentación de Ractive.

Y aquí está la implementación de la función 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]; }); }

Ampliación de la entrada para cada desarrollador

Ahora que tenemos una lista de trabajo de desarrolladores, es hora de agregar más detalles y, por supuesto, una buena 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}}

Nada nuevo aquí desde el lado Ractive de las cosas, pero un poco más de uso de las funciones de Bootstrap.

Visualización de una lista de habilidades de desarrollador en la que se puede hacer clic

Hemos hecho un buen progreso hasta ahora, pero una característica que aún falta es el otro lado de la relación desarrollador de habilidades; es decir, queremos mostrar las habilidades de cada desarrollador y queremos que cada una de esas habilidades sea un enlace en el que se pueda hacer clic que nos lleve a la vista de resultados de esa habilidad.

Pero espera... Estoy seguro de que ya tenemos exactamente lo mismo en la lista de habilidades. Sí, de hecho, lo hacemos. Está en la lista de habilidades en las que se puede hacer clic, pero proviene de un conjunto diferente al conjunto de habilidades de cada desarrollador. Sin embargo, estos son lo suficientemente similares como para que sea una señal clara para mí de que deberíamos reutilizar esa parte de HTML. Y con ese fin, los parciales son nuestros amigos.

(Nota: Ractive también tiene un enfoque más avanzado para fragmentos reutilizables de una vista, conocidos como componentes. Son bastante útiles, pero por simplicidad, no los discutiremos ahora).

Entonces, así es como logramos esto usando parciales (y tenga en cuenta, por cierto, que podemos agregar esta funcionalidad sin agregar una sola línea 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">&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}}

Ya tengo la lista de habilidades adjunta al objeto del desarrollador que recuperamos de la "base de datos", así que cambié un poco la plantilla: moví la línea que representa la etiqueta de habilidad a un parcial y usé este parcial donde estaba originalmente esa línea.

Luego, cuando repaso las habilidades del desarrollador, puedo reutilizar este mismo parcial nuevo para mostrar cada una de esas habilidades como un enlace en el que también se puede hacer clic. Además, esto también representa el evento select-skill si recuerdas, pasando el mismo nombre de habilidad. ¡Esto significa que podemos incluir esto en cualquier lugar (teniendo el contexto adecuado) y obtendremos una etiqueta en la que se puede hacer clic que conduce a la vista de habilidades!

Final Touch — Precargador

Bien, ahora tenemos una aplicación funcional básica. Es limpio y funciona rápido, pero aun así tarda un poco en cargarse. (En nuestro caso, esto se debe en parte a que usamos fuentes no concatenadas ni minificadas, pero en una aplicación del mundo real puede haber otras razones importantes, como la carga de datos iniciales).

Entonces, como paso final, le mostraré un buen truco para agregar una animación de precarga que se eliminará tan pronto como Ractive represente nuestra aplicación:

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

Entonces, ¿cuál es la magia aquí? En realidad es bastante simple. Agregué algo de contenido (es una barra de progreso animada de Bootstrap, pero podría ser un GIF animado o lo que sea) directamente a nuestro elemento raíz. Creo que es bastante inteligente: mientras nuestros scripts se están cargando, el usuario ve el indicador de carga (dado que no depende de JavaScript, se puede mostrar de inmediato). Sin embargo, tan pronto como se inicialice la aplicación Ractive, Ractive sobrescribirá el contenido del elemento raíz (y, por lo tanto, borrará la animación de precarga) con la plantilla renderizada. De esa manera, podemos lograr este efecto con solo una pieza de HTML estático y 0 líneas de lógica. Creo que eso es genial.

Conclusión

Piense en lo que hemos logrado aquí y cuán fácilmente lo hemos logrado. Tenemos una aplicación bastante completa: muestra una lista de habilidades, permite buscarlas rápidamente (e incluso admite la actualización interactiva de la lista de habilidades a medida que el usuario escribe en el cuadro de búsqueda), permite navegar a una habilidad en particular y volver, y enumera los desarrolladores para cada habilidad seleccionada. Además, podemos hacer clic en cualquier habilidad enumerada por cualquier desarrollador para acceder a la lista de desarrolladores con esa habilidad. Y todo eso con menos de 80 líneas de HTML y menos de 40 líneas de JavaScript. En mi opinión, eso es bastante impresionante y dice mucho sobre el poder, la elegancia y la simplicidad de Ractive.

Una versión funcional de la aplicación está disponible en línea aquí y el código fuente completo es público y está disponible aquí.

Por supuesto, apenas hemos arañado la superficie en este artículo de lo que es posible con el marco Ractive. Si le gusta lo que ha visto hasta ahora, le recomiendo que comience con la configuración de 60 segundos de Ractive y comience a explorar por sí mismo todo lo que Ractive tiene para ofrecer.