ejemplo - ¿Existe una mejor práctica para generar html con javascript?
title css (8)
Estoy llamando a un servicio web que devuelve una matriz de objetos en JSON. Quiero tomar esos objetos y poblar un div con HTML. Digamos que cada objeto contiene una url y un nombre.
Si quisiera generar el siguiente HTML para cada objeto:
<div><img src="the url" />the name</div>
¿Hay una mejor práctica para esto? Puedo ver algunas formas de hacerlo:
- Concatenar cadenas
- Crear elementos
- Use un plugin de plantillas
- Genere el html en el servidor, luego publíquelo a través de JSON.
¿Hay una mejor práctica para esto? Puedo ver algunas formas de hacerlo:
- Concatenar cadenas
- Crear elementos
- Use un plugin de plantillas
- Genere el html en el servidor, luego publíquelo a través de JSON.
1) Esta es una opción. Cree el html con JavaScript en el lado del cliente y luego inyéctelo en el DOM como un todo.
Tenga en cuenta que hay un paradigma detrás de este enfoque: el servidor genera solo datos y (en caso de interacción) recibe datos del cliente asyncronoulsy con las solicitudes AJAX. El código del lado del cliente funciona como una aplicación web de JavaScript independiente.
La aplicación web puede operar, renderizar la interfaz, incluso sin que el servidor esté activo (por supuesto, no mostrará ningún dato ni ofrecerá ningún tipo de interacción).
Este paradigma se está adoptando a menudo últimamente, y los marcos completos se basan en este enfoque (ver backbone.js, por ejemplo).
2) Por razones de rendimiento, cuando sea posible, es mejor construir el html en una cadena y luego inyectarlo como un todo en la página.
3) Esta es otra opción, además de adoptar un marco de aplicación web. Otros usuarios han publicado varios motores de plantillas disponibles. Tengo la impresión de que tiene las habilidades para evaluarlos y decidir si seguir este camino o no.
4) Otra opción. Pero sírvelo como un texto simple / html; ¿Por qué JSON? No me gusta este enfoque porque mezcla PHP (el idioma de tu servidor) con Html. Pero lo adopto a menudo como un compromiso razonable entre las opciones 1 y 4 .
Mi respuesta: ya estás mirando en la dirección correcta.
Sugiero adoptar un enfoque entre 1 y 4 como lo hago. De lo contrario, adopte un marco web o motor de plantillas.
Solo mi opinión basada en mi experiencia ...
Aquí hay un ejemplo, usando mi complemento Simple Templates para jQuery:
var tmpl = ''<div class="#{classname}">#{content}</div>'';
var vals = {
classname : ''my-class'',
content : ''This is my content.''
};
var html = $.tmpl(tmpl, vals);
Cualquiera de las dos primeras opciones es común y aceptable.
Daré ejemplos de cada uno en Prototype .
// assuming JSON looks like this:
// { ''src'': ''foo/bar.jpg'', ''name'': ''Lorem ipsum'' }
Enfoque n. ° 1:
var html = "<div><img src=''#{src}'' /> #{name}</div>".interpolate(json);
$(''container'').insert(html); // inserts at bottom
Enfoque # 2:
var div = new Element(''div'');
div.insert( new Element(''img'', { src: json.src }) );
div.insert(" " + json.name);
$(''container'').insert(div); // inserts at bottom
Divulgación: soy el mantenedor de BOB.
Hay una biblioteca de JavaScript que facilita mucho este proceso llamado BOB .
Para su ejemplo específico:
<div><img src="the url" />the name</div>
Esto se puede generar con BOB mediante el siguiente código.
new BOB("div").insert("img",{"src":"the url"}).up().content("the name").toString()
//=> "<div><img src="the url" />the name</div>"
O con la sintaxis más corta
new BOB("div").i("img",{"src":"the url"}).up().co("the name").s()
//=> "<div><img src="the url" />the name</div>"
Esta biblioteca es bastante poderosa y puede usarse para crear estructuras muy complejas con la inserción de datos (similar a d3), por ej .:
data = [1,2,3,4,5,6,7]
new BOB("div").i("ul#count").do(data).i("li.number").co(BOB.d).up().up().a("a",{"href": "www.google.com"}).s()
//=> "<div><ul id="count"><li class="number">1</li><li class="number">2</li><li class="number">3</li><li class="number">4</li><li class="number">5</li><li class="number">6</li><li class="number">7</li></ul></div><a href="www.google.com"></a>"
BOB actualmente no es compatible con inyectar los datos en el DOM. Esto está en el todolist. Por ahora puede simplemente usar la salida junto con JS normal o jQuery, y ponerlo donde desee.
document.getElementById("parent").innerHTML = new BOB("div").insert("img",{"src":"the url"}).up().content("the name").s();
//Or jquery:
$("#parent").append(new BOB("div").insert("img",{"src":"the url"}).up().content("the name").s());
Hice esta biblioteca porque no estaba satisfecho con ninguna de las alternativas como jquery y d3. El código es muy complicado y difícil de leer. Trabajar con BOB es, en mi opinión, obviamente obvio, mucho más agradable.
BOB está disponible en Bower , por lo que puede obtenerlo ejecutando bower install BOB
.
Las opciones n. ° 1 y n. ° 2 serán sus opciones directas más inmediatas, sin embargo, para ambas opciones, sentirá el impacto en el rendimiento y el mantenimiento al construir cadenas o crear objetos DOM.
Las plantillas no son tan inmaduras, y lo estás viendo emergente en la mayoría de los principales frameworks de Javascript.
Aquí hay un ejemplo en el complemento de plantilla de JQuery que le ahorrará el golpe de rendimiento, y es muy, muy sencillo:
var t = $.template(''<div><img src="${url}" />${name}</div>'');
$(selector).append( t , {
url: jsonObj.url,
name: jsonObj.name
});
Digo que sigan la ruta genial (y de mejor rendimiento, más fácil de mantener) y utilicen la creación de plantillas.
Puede agregar la plantilla HTML a su página en un div oculto y luego usar cloneNode y las instalaciones de consulta de su biblioteca favorita para poblarlo
/* CSS */
.template {display:none;}
<!--HTML-->
<div class="template">
<div class="container">
<h1></h1>
<img src="" alt="" />
</div>
</div>
/*Javascript (using Prototype)*/
var copy = $$(".template .container")[0].cloneNode(true);
myElement.appendChild(copy);
$(copy).select("h1").each(function(e) {/*do stuff to h1*/})
$(copy).select("img").each(function(e) {/*do stuff to img*/})
Si absolutamente tiene que concatenar cadenas, en lugar de lo normal:
var s="";
for (var i=0; i < 200; ++i) {s += "testing"; }
usa una matriz temporal:
var s=[];
for (var i=0; i < 200; ++i) { s.push("testing"); }
s = s.join("");
Usar matrices es mucho más rápido, especialmente en IE. Hice algunas pruebas con cuerdas hace un tiempo con IE7, Opera y FF. Opera solo tomó 0.4 segundos para realizar la prueba, ¡pero IE7 no había terminado después de 20 MINUTOS! (No, no estoy bromeando). Con array IE fue muy rápido.
Tal vez un enfoque más moderno es utilizar un lenguaje de plantillas como Mustache.js , que tiene implementaciones en muchos idiomas, incluido javascript. Por ejemplo:
var view = {
url: "/hello",
name: function () {
return ''Jo'' + ''hn'';
}
};
var output = Mustache.render(''<div><img src="{{url}}" />{{name}}</div>'', view);
Incluso obtiene un beneficio adicional: puede reutilizar las mismas plantillas en otros lugares, como el lado del servidor.
Si necesita plantillas más complicadas (sentencias if, bucles, etc.), puede usar Handlebars que tiene más funciones y es compatible con Moustache.