1. Code
  2. JavaScript

Mejores prácticas al trabajar con plantillas de JavaScript

Scroll to top

Spanish (Español) translation by Juan Pablo Diaz Cuartas (you can also view the original English article)

Tal vez no los necesite para aplicaciones web sencillas, pero no requiere demasiada complejidad antes de aceptar plantillas de JavaScript se convierte en una buena decisión. Como cualquier otra herramienta o técnica, hay algunas prácticas recomendadas que debe tener en cuenta al usar plantillas. Veremos un puñado de estas prácticas en este tutorial.


1. Subrayar para Simple, manubrios para complejo

Si necesita algo con un poco más de entusiasmo, ¿podría recomendar manubrios?

Lo primero es lo primero: a menos que sea John Resig, lo más probable es que desee elegir una biblioteca bien probada para ofrecer la funcionalidad de su plantilla. Si bien las opciones son casi infinitas, existen dos opciones realmente buenas, según la complejidad de su proyecto.

Si el proyecto es relativamente simple, puede usar Underscore.js. En su mayor parte, esta biblioteca ofrece utilidades de programación funcional, pero tiene un método _.template que no podría facilitar las cosas. De forma predeterminada, utiliza los delimitadores de tipo ERB-esque <% =%>, pero eso se puede modificar fácilmente. La belleza de esta solución es que cualquier proyecto que requiera plantillas probablemente ya tendrá un subrayado cargado, simplemente debido a su gran utilidad general. Para obtener más información acerca de Underscore, consulte el tutorial completo de Siddharth aquí en Nettuts +.

Si necesita algo con un poco más de entusiasmo, ¿podría recomendar manubrios? Con muchas expresiones de bloque útiles (como #each para bucles y #if para condicionales) y la posibilidad de registrar sus propias funciones de ayuda, Handlebars le dará todo lo que necesita para crear incluso las plantillas más complejas.

Si no está familiarizado con los manubrios, Gabriel Manricks lo tiene cubierto en este tutorial.

Por supuesto, hay otras bibliotecas de plantillas por ahí; ¡Siéntete libre de revisarlos! Solo recomiendo estos dos porque los disfruto y los uso yo mismo. También tienden a ser las ofertas más populares en la comunidad.

HandlebarsHandlebarsHandlebars
Handlebars es un excelente motor de plantillas de JavaScript.

2. Crear funciones de Template Helper

La mayoría de las bibliotecas de plantillas harán que el objeto de datos que pase a la plantilla funcione como el contexto.

Habrá momentos en los que los datos que está insertando en una plantilla no estarán formateados del modo que prefiera. En estas situaciones, deberá crear funciones personalizadas para formatearlo. Si está utilizando algo como manubrios, puede registrar fácilmente una función auxiliar; pero otras soluciones, como Underscore, no ofrecen esa funcionalidad. Tendrás que hacer el tuyo.

La razón por la que esto no es tan simple como podría sonar es porque la mayoría de las bibliotecas de plantillas harán que el objeto de datos que pase a la plantilla funcione como el contexto o el valor de this. Por lo tanto, la función debe ser parte de este objeto. Hay un par de maneras de hacer esto. La forma principal es agregar la función al objeto de datos antes de pasarlo a la función de plantilla. Aquí hay un ejemplo:

1
// assume data object and template function

2
3
data.formatPrice = function (priceInCents) {
4
    return "$" + (priceInCents / 100).toFixed(2);
5
}
6
7
var html = template(data);

Esto es ideal para situaciones excepcionales, pero es posible que tenga múltiples conjuntos de plantillas, cada una de las cuales necesita su propio conjunto de funciones de ayuda. Lo que me gustaría hacer en estos casos es ajustar la función de plantilla en otra función que aplicará los ayudantes al objeto de datos.

1
var productTemplate = function (data) {
2
    var template = _.template("the template string");
3
    data.helperFunction1 = function () { return "whatever" };
4
    return template(data);
5
};

Hay varias maneras de mejorar esto (puede comenzar con el almacenamiento en caché de la función de plantilla "en bruto" fuera de esta función, probablemente a través de un cierre), pero esa es la idea básica. Ahora, simplemente puede pasar sus datos a esa plantilla de producto y tener acceso a sus funciones auxiliares.


3. Almacene las plantillas en su propio archivo

Existen varias soluciones alternativas que podrían ser mejores, especialmente en escenarios más complejos.

Todas las plantillas de JavaScript obviamente comienzan como texto. El lugar más popular (y natural) para almacenarlos está dentro de su documento HTML, generalmente en una etiqueta de script con un atributo de tipo alternativo, de modo que el navegador no intente ejecutarlos. Es bastante fácil tomar el atributo innerHTML de la etiqueta de script y pasarlo a la función de creación de plantilla, cuando esté listo.

Sin embargo, esta no es la única forma de hacerlo; de hecho, puede que no sea la forma óptima. Existen varias soluciones alternativas que podrían ser mejores, especialmente en escenarios más complejos.

La primera alternativa es almacenarlos todos dentro de un archivo JavaScript. Por supuesto, esto significa que sus plantillas se almacenarán como cadenas en lugar del HTML sangrado más legible, ¡pero quédense conmigo por un segundo! En primer lugar, para las plantillas que son más largas que una sola línea (la mayoría de las plantillas), no es necesario usar una cadena envolvente difícil de manejar. En cambio, intente algo como esto:

1
Templates = {};
2
3
Templates.contactEntry = [
4
    "<h1> {{fullName}} </h1>",
5
    "<ul>",
6
        "<li> Email: {{email}} </li>",
7
        "<li> Phone: {{tel}} </li>",
8
    "</ul>"
9
].join("\n");

Almacenar una plantilla en una matriz como esta hace que sea mucho más fácil de manejar. Al usar una sintaxis como esta, puede almacenar fácilmente todas sus plantillas en su propio archivo JavaScript, y tener ese archivo cargado en la página antes de que necesite las plantillas. Y, por supuesto, no tiene que mantenerlos todos dentro de un único objeto Plantilla, pero mantiene las cosas organizadas. Ese objeto de Templates podría incluso ser una propiedad en su objeto de aplicación global (como en MyApp.Templates).

Pero espera, hay más (para acuñar una frase). Puede convertir todas sus plantillas a sus respectivas funciones de plantilla en un solo ciclo:

1
for (var tmpl in Templates) {
2
    if (Templates.hasOwnProperty(tmpl) {
3
        Templates[t] = _.template(Templates[t]); // Underscore example

4
    }
5
}

Si está usando AMD en su aplicación, este método seguirá funcionando; solo ponlo en un módulo de plantillas que devuelve ese objeto de Plantillas. Sin embargo, muchas soluciones de AMD tienen un complemento de texto que le permite cargar archivos de texto sin formato; en lugar del objeto de módulo normal, obtendrás una cadena a cambio. Si está utilizando la biblioteca RequireJS, deberá incluir el complemento text.js en el mismo directorio que el archivo require.js. Entonces, puedes hacer algo como:

1
require(["text!templates/document.html"], function (documentTemplate) {
2
3
});

Ese parámetro documentTemplate será una cadena que contiene los contenidos que se encuentran en ese archivo templates / document.html. Al hacerlo de esta manera, no podrá poner varias plantillas en un solo archivo, a menos que desee manipular esa cadena.


4. Precompila tus plantillas

Si usa Asset Pipeline en una aplicación de Rails, aproveche los Sprockets para precompilar las funciones de la plantilla.

Si lo piensas por un segundo, el navegador realiza un trabajo adicional cada vez que creas una plantilla. Generalmente, esa plantilla comienza como una cadena que pasa a una función de creación de plantilla. Esa función devuelve otra función, de la que puede pasar los datos y recibir HTML. El trabajo adicional es la parte "crear la plantilla-función"; no hay ninguna razón por la cual esto no se pueda hacer antes de que se envíe el JavaScript al cliente. Preferiblemente, podría agregar agregar este trabajo a su proceso de compilación, junto con minimizar su CSS y concatenar su JS.

Desafortunadamente, las plantillas de JavaScript precompiladas no son tan simples como minificar o concatenar ... al menos, todavía no, probablemente debido a las muchas formas de crear plantillas. Si está usando Grunt o Yeoman, puede buscar complementos (como este) en el sitio web de Grunt. Si está utilizando Asset Pipeline en una aplicación de Rails, puede aprovechar los Sprockets para precompilar sus funciones de plantilla.

Ah, y si eres aventurero (y un suscriptor de Tuts + Premium), puedes unirte a mí ya que precompilo plantillas desde cero en mi curso Advanced Backbone Patterns and Techniques.


5. Sin evaluación en plantillas

Sin evaluación en plantillas.

No hace mucho tiempo, mientras investigaba para otro proyecto, encontré una idea interesante sobre las plantillas de JavaScript en el excelente libro Recipes with Backbone. Desde entonces se ha convertido en una práctica recomendada en la comunidad: no hay evaluación en plantillas. Por supuesto, la interpolación de variables es, estrictamente hablando, evaluación, pero a lo que me refiero más aquí es a código lógico. Puedes poner el JavaScript que quieras dentro de las etiquetas de delimitación, pero puede salirse de control fácilmente. Todos sabemos que se considera una buena práctica mantener separados sus HTML, CSS y JavaScript; esto hace que sea más fácil hacer un seguimiento del código y detectar errores, cuando sea necesario. Lo mismo es cierto para las plantillas: deben ser solo un lugar para la interpolación de valores. Cualquier lógica o transformación de datos debe realizarse fuera de la plantilla.

Por supuesto, qué tan lejos llegues con esta idea depende de ti. Puede decidir que el bucle dentro de sus plantillas está bien; es posible que tenga una plantilla como esta:

1
<h1> My List </h1>
2
<ul id="myList">
3
    <% list.forEach(function (item) { %>
4
        <li> <%= item.name %> </li>
5
    <% }); %>
6
</ul>

O, en su lugar, puede optar por realizar un bucle fuera de las plantillas creando una plantilla contenedora y, a continuación, colocando un bucle sobre los elementos, representando una sub-plantilla e insertándola en la plantilla contenedora. Puede terminar con dos plantillas como esta:

La plantilla de envoltura:

1
<h1> My List </h1>
2
<ul id="myList">
3
</ul>

La sub-plantilla:

1
<li> <%= name %> </li>

Por supuesto, este método separado genera un poco más de código, pero a la larga lo valdrá la pena.

En esta línea, es una buena práctica seguir el ejemplo del marco o la biblioteca que está utilizando. Por ejemplo, he descubierto que, al usar Backbone con plantillas de subrayado, es más fácil usar bucles y subpáginas externos: la funcionalidad de plantilla mínima de Underscore no ofrece ninguna sintaxis de bucle, y el método de renderizado de Backbone es un gran lugar para hacer ese bucle e insertando las sub-plantillas. Sin embargo, al usar Meteor, que se basa en las plantillas de manubrios, es mucho más fácil recorrer las plantillas con un #each bloque; (y use sub-plantillas, también, si lo desea).


6. Enlace datos a las plantillas

Conozca más sobre Backbone.stickit en Tuts + Premium.

Esto no siempre será aplicable, pero, en algunos casos, puede ser realmente útil hacer que las plantillas se actualicen automáticamente cuando cambien los datos que muestran. Me gusta mucho esta idea, porque permite que incluso la IU de tu aplicación sea completamente basada en datos: cuando un atributo de modelo se actualiza, la UI se actualiza con él. Este es el principio básico detrás de las herramientas, como Knockout.

Si bien es probable que puedas implementar esta funcionalidad por tu cuenta sin demasiados problemas, todos los marcos populares la tienen incorporada. Por ejemplo, en Backbone, la función de inicialización de una plantilla puede incluir algunos oyentes de eventos personalizados, como los siguientes:

1
this.model.on('change', this.render, this);

De esta forma, siempre que un atributo de modelo cambie, se invocará la función de representación de la plantilla y se volverá a representar la plantilla. Alternativamente, puede usar un complemento, como backbone.stickit, que administrará los enlaces por usted. Si está trabajando con Meteor y usando una de sus fuentes de datos reactivos, obtendrá este enlace de forma gratuita, sin necesidad de trabajo adicional. No estoy lo suficientemente familiarizado con ningún otro marco para saber exactamente cómo lo hacen, pero cualquier marco que valga la pena usar debería tener una característica similar.


7. Simplifica tus plantillas

Muy rápidamente, sus plantillas pueden salir de control y volverse difíciles de manejar.

Si no tiene cuidado, muy rápidamente, sus plantillas pueden salir de control y volverse difíciles de manejar. Es por eso que siempre es una buena idea limitar sus plantillas a un tamaño razonable. Si los haces demasiado grandes, serán más difíciles de actualizar y no permitirán una buena separación del código. Por otro lado, si son demasiado pequeños, costarán demasiado por lo que traen, y posteriormente ralentizarán tu aplicación.

Es por eso que es importante encontrar un medio feliz. Acércate a tus plantillas de la misma manera que escribes tu código JavaScript o CSS: hazlo modular. Sí, cada "fragmento" o widget de UI debe tener su propia plantilla, pero no se olvide de las subpáginas. Son útiles cuando las unidades más pequeñas de un widget tienen diseños o estados complejos, así como cuando tienen múltiples eventos, pero recuerde que pueden ser un arma de doble filo. No los uses a menos que tengas una buena razón para hacerlo.


8. No los uses si no los necesitas

Finalmente, recuerde que las plantillas de JavaScript son solo una herramienta más en su caja; y, a veces, simplemente no es el adecuado para el trabajo. No use plantillas donde no las necesite. Use su cabeza: puede haber otras situaciones, cuando una plantilla no es la mejor herramienta.


Conclusión

Bueno, esos son mis mejores consejos para usar plantillas de JavaScript, ¡pero quizás puedas pensar en algunos más! Si es así, por favor compártalos en los comentarios a continuación, para que podamos continuar la discusión.