2010-02-14 3 views
5

J'essaie de développer un moyen simple de créer des modèles en JavaScript. L'idée de base est que j'ai le HTML dans une page qui représente l'interface utilisateur d'un objet en JavaScript, et les variables dans ce HTML qui sont remplacées par les propriétés de l'objet JavaScript. Pensez-y comme technique pour lier des objets JavaScript à des présentations HTML.Amélioration d'une simple technique de création de modèle JavaScript

Des critiques? Dois-je utiliser des fragments de document en quelque sorte? Je suis essentiellement à la recherche d'un code de révision sur celui-ci. J'apprécierais tout commentaire. (Notez que ceci devrait être indépendant du framework.) Voici un exemple fonctionnel.

<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 pour // magic – cherouvim

+0

Haha, merci! :) – JamesBrownIsDead

Répondre

2

Le code est pur.

Je voudrais avoir le modèle dans un commentaire html donc 1) il n'est pas rendu (pas besoin de l'affichage: aucun hack) et 2) Je serais en mesure d'avoir des choses qui ne valide pas, comme comme direct un <tr>. En outre, je supprimerais la création 'div' codée en dur afin que je puisse prendre en charge les extraits de modèles commençant par n'importe quel élément HTML.

Plus tard, j'ajouterais la navigation graphique (par exemple $ {foo.bar}), l'itération et les instructions if.

2

+1 cherouvim: vous utilisez le modèle comme texte, alors gardez le comme texte. Vous pouvez le passer à votre script en tant que commentaire, ou vous pouvez le faire passer en tant que chaîne codée en JSON, mais l'utilisation de balisage est potentiellement dangereuse.

Par exemple:

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

illustre certaines choses que vous ne pouvez pas faire de manière fiable dans votre langue templating en raison du navigateur « fixation » le balisage et la modification du retour innerHTML arrière: le form peut muter à method="get" (ou, dans IE, FSR omis); sauf si vous êtes en mode XML, un élément <tbody> sera ajouté; l'élément mutable ne fonctionnera pas du tout; le texte ${extrarow} n'est pas valide directement à l'intérieur d'une table; le input.value peut être muté au chargement de la page lorsque les navigateurs tentent de redéfinir les valeurs du champ de formulaire et que IE reflète de manière incorrecte les modifications de la valeur du champ en tant qu'attributs/innerHTML.

Aussi, je recommande fortement l'ajout d'une fonctionnalité HTML-encode (remplacement & avec &amp;, < avec &lt; et les délimiteurs de valeur d'attribut avec des références similaires). L'expérience des langages de création de modèles a montré qu'il est beaucoup plus courant de vouloir insérer une chaîne de caractères dans le document qu'une extension de balisage. Lorsque vous faites:

Hello, ${name}! 

sans appliquer échapper à la name variable vous ouvrez votre application à des attaques cross-site scripting-. Les langages de modèles modernes évitent cela en appliquant le codage HTML par défaut, car les codeurs sont beaucoup trop paresseux pour le faire manuellement (s'ils comprennent même les problèmes impliqués). C'est pourquoi la grande majorité des applications PHP sont vulnérables aux attaques XSS.

N'apportez pas le même problème au client; faire échapper par défaut, offrant un drapeau pour dire que vous ne voulez pas échapper aux (habituellement relativement peu) les cas où vous souhaitez insérer le balisage brut:

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

La fonction d'encodage html serait géniale – cherouvim

1

Plutôt que d'avoir dans un commentaire HTML, vous pouvez mettre dans les balises, par exemple:

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

La beauté est que tous les navigateurs et tous les robots correctement écrits ignoreront les blocs de script où il ne sait pas comment les interpréter; et vous pouvez facilement accéder au contenu via l'ID (comme si c'était un div).

+0

Voici comment plusieurs plugins de templates jQuery fonctionnent ainsi que la proposition de template de Microsoft. http://wiki.github.com/nje/jquery/jquery-templates-proposal – R0MANARMY

Questions connexes