2010-02-14 12 views
5

Estoy tratando de desarrollar una forma simple de crear plantillas en JavaScript. La idea básica es que tengo HTML en una página que representa la UI de un objeto en JavaScript y las variables en ese HTML que se reemplazan con las propiedades del objeto JavaScript. Piense en ello como una técnica para enlazar objetos JavaScript a presentaciones HTML.Mejora de una técnica de plantillas de JavaScript simple

¿Alguna crítica? ¿Debo usar fragmentos de documentos de alguna manera? Básicamente, estoy buscando una revisión del código en este caso. Agradecería cualquier comentario. (Tenga en cuenta que esto debería ser independiente del marco.) Aquí hay un ejemplo de trabajo.

<html> 
<body> 

    <!-- where templates will be injected into --> 
    <div id="thumbContainer"></div> 

    <!-- template used for thumbnails --> 
    <div id="thumbTemplate" style="display:none"> 
     <div class="thumb"> 
      <div>${caption}</div> 
      <div>${image}</div> 
     </div> 
    </div> 

</body> 

<script type="text/javascript"> 
(function() { 

    // Cache the templates' markup in case that template is used again 

    var cache = []; 

    // Magic 

    document.templatized = function(templateId, properties) { 

     // Get the template from cache or get template and add to cache 

     var template = cache[templateId] || (function() { 
      cache[templateId] = document.getElementById(templateId).innerHTML; 
      return cache[templateId]; 
     })(); 

     // Create the DOM elements that represent the markup 

     var shell = document.createElement('div'); 

     shell.innerHTML = template.replace(/\$\{(\w+)\}/g, function(match, key){ 
      return properties[key] || match; 
     }); 

     // Return those DOM elements 

     return shell.children[0].cloneNode(true); 
    }; 
})(); 

// Create DOM elements with values bound to thumbnail object 

var thumb = document.templatized('thumbTemplate', { 
    caption: 'Summer', 
    image: (function() { 
      // More complicated logic that requires conditions here... 
     return '<img src="test.png" />'; 
    })() 
}); 

// Display on page by inserting into DOM 

document.getElementById('thumbContainer').appendChild(thumb); 
</script> 
+0

+1 para // magia – cherouvim

+0

¡Jaja, gracias! :) – JamesBrownIsDead

Respuesta

2

El código es limpio.

Tendría la plantilla en un comentario en html, así que 1) no se procesa (no es necesario mostrar: ninguno) y 2) podría tener cosas que no validen, tales como directo a <tr>.

Además, eliminaría la creación de 'div' codificada para poder admitir fragmentos de plantillas comenzando con cualquier elemento html.

Más adelante agregaría la navegación de gráficos (por ejemplo, $ {foo.bar}), la iteración y las declaraciones if.

2

+1 cherouvim: está usando la plantilla como texto, así que guárdela como texto. Podría pasarlo a su secuencia de comandos como un comentario, o podría simplemente pasarlo como una cadena codificada JSON, pero el uso de marcado es potencialmente peligroso.

Por ejemplo:

<form method="${mymethod}"><table> 
    <tr><td> 
     <${mylisttype}> 
      <li> 
       <input name="foo" value="${myvalue}"> 
      </li> 
     </${mylisttype}> 
    </td></tr> 
    ${extrarow} 
</table></form> 

ilustra algunas cosas que no puede hacer de forma fiable en su lenguaje de plantillas debido al navegador 'fijar' el margen de beneficio y cambiando la innerHTML volver devuelto: la form puede mutarse a method="get" (o, en IE, se omite FSR); a menos que esté en modo XML habrá un elemento <tbody> agregado; el elemento mutable no funcionará en absoluto; el texto ${extrarow} no es válido directamente dentro de una tabla; el input.value puede mutarse en la carga de la página a medida que los navegadores intentan restablecer los valores del campo del formulario y IE refleja incorrectamente los cambios del valor del campo como atributos/innerHTML.

También, recomendaría fuertemente la adición de una característica HTML-encode (reemplazando & con &amp;, < con &lt; y cualquier delimitadores de valor de atributo con referencias similares). La experiencia con la creación de plantillas ha demostrado que es mucho más común querer insertar una cadena de texto en el documento que una extensión de marcado. Cuando lo haga:

Hello, ${name}! 

sin aplicar escapar a la variable name, que está abriendo su aplicación a los ataques-site-scripting cruz. Los lenguajes de plantillas modernos evitan esto al aplicar codificación HTML de manera predeterminada, porque los codificadores son demasiado flojos para hacerlo manualmente (incluso si entienden los problemas involucrados). Esta es la razón por la cual la gran mayoría de las aplicaciones PHP son vulnerables a los ataques XSS.

No traiga el mismo problema al lado del cliente; hacen escapar por defecto, ofreciendo una bandera que decir que no quiere escapar de las (por lo general relativamente pocos) casos en los que desee insertar el formato en bruto:

<div>${caption}</div> 
<div>${image|markup}</div> 
+1

característica de codificación html sería genial – cherouvim

1

En lugar de tener que en un comentario HTML que pueda ponerlo en las etiquetas, por ejemplo:

<script type="text/html" id="mytemplate"> 
    ... template here ... 
</script> 

La belleza aquí es que todos los navegadores y todos los robots correctamente escritas ignorarán los bloques de script en el que no saben cómo interpretarlas; y puede acceder fácilmente al contenido a través de la ID (como si fuera un div).

+0

Así es como varios plugins de plantillas jQuery funcionan tan bien como la propuesta de plantillas de Microsoft. http://wiki.github.com/nje/jquery/jquery-templates-proposal – R0MANARMY

Cuestiones relacionadas