web-dev-qa-db-fra.com

Comment utiliser underscore.js comme moteur de template?

J'essaie de découvrir les nouveaux usages de javascript comme langage serveur et comme langage fonctionnel. Il y a quelques jours, j'ai entendu parler de node.js and express framework. Ensuite, j'ai vu le underscore.js comme un ensemble de fonctions utilitaires. J'ai vu cette question sur stackoverflow . Cela dit que nous pouvons utiliser underscore.js comme moteur de template. Tout le monde connaît de bons tutoriels sur l’utilisation de underscore.js pour la modélisation, en particulier pour les utilisateurs plus expérimentés qui ont moins d’expérience du javascript avancé. Merci

258
knodumi

Tout ce que vous devez savoir sur le modèle de soulignement est ici . Seulement 3 choses à garder à l'esprit:

  1. <% %> - pour exécuter du code
  2. <%= %> - pour imprimer une valeur dans un modèle
  3. <%- %> - pour imprimer certaines valeurs HTML échappées

C'est tout à propos de ça.

Exemple simple:

var tpl = _.template("<h1>Some text: <%= foo %></h1>");

alors tpl({foo: "blahblah"}) serait rendu à la chaîne <h1>Some text: blahblah</h1>

466
SET
<!-- Install jQuery and underscore -->

<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="http://documentcloud.github.com/underscore/underscore-min.js"></script>

<!-- Create your template -->
<script type="foo/bar" id='usageList'>
<table cellspacing='0' cellpadding='0' border='1' >
    <thead>
      <tr>
        <th>Id</th>
        <th>Name</th>
      </tr>
    </thead>
    <tbody>
      <%
        // repeat items 
        _.each(items,function(item,key,list){
          // create variables
          var f = item.name.split("").shift().toLowerCase();
      %>
        <tr>
          <!-- use variables -->
          <td><%= key %></td>
          <td class="<%= f %>">
            <!-- use %- to inject un-sanitized user input (see 'Demo of XSS hack') -->
            <h3><%- item.name %></h3>
            <p><%- item.interests %></p>
          </td>
        </tr>
      <%
        });
      %>
    </tbody>
  </table>
</script>

<!-- Create your target -->

<div id="target"></div>

<!-- Write some code to fetch the data and apply template -->

<script type="text/javascript">
  var items = [
    {name:"Alexander", interests:"creating large empires"},
    {name:"Edward", interests:"ha.ckers.org <\nBGSOUND SRC=\"javascript:alert('XSS');\">"},
    {name:"..."},
    {name:"Yolando", interests:"working out"},
    {name:"Zachary", interests:"picking flowers for Angela"}
  ];
  var template = $("#usageList").html();
  $("#target").html(_.template(template,{items:items}));
</script>
  • JsFiddle Merci @PHearst!
  • JsFiddle (dernière)
  • JsFiddle Liste groupée par première lettre (exemple complexe avec images, appels de fonction, sous-modèles) avoir un souffle ...
  • JsFiddle Démo du hack XSS noté par @tarun_telang ci-dessous
  • JsFiddle Une méthode non standard pour créer des sous-modèles
198
Shanimal

Dans sa forme la plus simple, vous l'utiliseriez comme ceci:

var html = _.template('<li><%= name %></li>', { name: 'John Smith' });
//html is now '<li>John Smith</li>'   

Si vous utilisez un modèle plusieurs fois, vous voudrez le compiler pour que ce soit plus rapide:

var template = _.template('<li><%= name %></li>');

var html = [];
for (var key in names) {
    html += template({ name: names[i] });
}

console.log(html.join('')); //Outputs a string of <li> items

Personnellement, je préfère la syntaxe de style Moustache. Vous pouvez ajuster les marqueurs de jeton de modèle pour utiliser des accolades doubles:

_.templateSettings.interpolate = /\{\{(.+?)\}\}/g;

var template = _.template('<li>{{ name }}</li>');
93
evilcelery

La documentation pour la modélisation est partielle, j'ai regardé la source.

La fonction _. Template a 3 arguments:

  1. Chaîne texte: la chaîne de modèle
  2. Objet data: les données d'évaluation
  3. Objet paramètres: paramètres locaux, le _. TemplateSettings est l'objet de paramètres généraux

Si aucun données (ou null) n'est donné, alors une fonction rendre sera retournée. Il a 1 argument:

  1. Objet data: identique au data ci-dessus

Il y a 3 motifs de regex et 1 paramètre statique dans les paramètres:

  1. RegExp assessment: "<% code%>" dans la chaîne de modèle
  2. RegExp interpolate: "<% = code%>" dans la chaîne de modèle
  3. RegExp escape: "<% - code%>"
  4. Chaîne variable: facultatif, nom du paramètre data dans la chaîne de modèle

Le code dans une section evaluer sera simplement évalué. Vous pouvez ajouter une chaîne à partir de cette section avec la commande __ p + = "mystring" au modèle évalué, mais cela n'est pas recommandé (ne faisant pas partie de l'interface de modélisation), utilisez plutôt la section interpoler. Ce type de section permet d’ajouter des blocs comme if ou for au modèle.

Le résultat du code dans la section interpolate sera ajouté au modèle évalué. Si null est rendu, une chaîne vide sera ajoutée.

La section escape échappe au langage HTML avec _. Escape sur la valeur de retour du code donné. Donc, il ressemble à un _. Escape (code) dans une section interpolate, mais il s'échappe avec \ les espaces blancs comme \n avant qu’il ne passe le code au _. evasion. Je ne sais pas pourquoi c'est important, c'est dans le code, mais ça marche bien avec les caractères interpolate et _. Escape - qui n'échappent pas au blanc personnages - aussi.

Par défaut, le paramètre data est transmis par une instruction with (data) {...}, mais ce type d'évaluation est beaucoup plus lent que l'évaluation avec une variable nommée. Donc, nommer les données avec le paramètre variable est quelque chose de bien ...

Par exemple:

var html = _.template(
    "<pre>The \"<% __p+=_.escape(o.text) %>\" is the same<br />" +
        "as the  \"<%= _.escape(o.text) %>\" and the same<br />" +
        "as the \"<%- o.text %>\"</pre>",
    {
        text: "<b>some text</b> and \n it's a line break"
    },
    {
        variable: "o"
    }
);

$("body").html(html);

résultats

The "<b>some text</b> and 
 it's a line break" is the same
as the "<b>some text</b> and 
 it's a line break" and the same
as the "<b>some text</b> and 
 it's a line break"

Vous trouverez ici d'autres exemples d'utilisation du modèle et de substitution des paramètres par défaut: http://underscorejs.org/#template

Lors du chargement du modèle, vous avez beaucoup d'options, mais à la fin, vous devez toujours convertir le modèle en chaîne. Vous pouvez lui attribuer une chaîne normale, comme dans l'exemple ci-dessus, ou le charger à partir d'une balise de script et utiliser la fonction . Html () de jquery, ou le charger à partir d'un fichier séparé avec le plugin tpl de require.js .

Une autre option consiste à construire l’arbre dom avec laconique au lieu de créer un modèle.

28
inf3rno

Je donne un exemple très simple

1)

var data = {site:"mysite",name:"john",age:25};
var template = "Welcome you are at <%=site %>.This has been created by <%=name %> whose age is <%=age%>";
var parsedTemplate = _.template(template,data);
console.log(parsedTemplate); 

Le résultat serait

Welcome you are at mysite.This has been created by john whose age is 25.

2) Ceci est un modèle

   <script type="text/template" id="template_1">
       <% _.each(items,function(item,key,arr) { %>
          <li>
             <span><%= key %></span>
             <span><%= item.name %></span>
             <span><%= item.type %></span>
           </li>
       <% }); %>
   </script>

C'est html

<div>
  <ul id="list_2"></ul>
</div>

C’est le code javascript qui contient l’objet json et le template en HTML

   var items = [
       {
          name:"name1",
          type:"type1"
       },
       {
          name:"name1",
          type:"type1"
       },
       {
          name:"name1",
          type:"type1"
       },
       {
          name:"name1",
          type:"type1"
       },
       {
          name:"name1",
          type:"type1"
       } 
   ];
  $(document).ready(function(){
      var template = $("#template_1").html();
      $("#list_2").html(_.template(template,{items:items}));
  });
22
dinesh_malhotra

avec express c'est si facile. tout ce dont vous avez besoin est d'utiliser le module consolider sur le noeud, vous devez donc l'installer:

npm install consolidate --save

alors vous devriez changer le moteur par défaut en template HTML par ceci:

app.set('view engine', 'html');

enregistrez le moteur de gabarit de soulignement pour l'extension html:

app.engine('html', require('consolidate').underscore);

c'est fait !

Maintenant, chargez par exemple un modèle appelé 'index.html':

res.render('index', { title : 'my first page'});

peut-être aurez-vous besoin d'installer le module de soulignement.

npm install underscore --save

J'espère que cela vous a aidé!

14
Khalid Ahmada

Je voulais partager une autre découverte importante.

l'utilisation de <% = variable => entraînerait une vulnérabilité de script intersite. Il est donc plus sûr d’utiliser plutôt <% - variable ->.

Nous avons dû remplacer <% = par <% - pour empêcher les attaques de script entre sites. Je ne sais pas si cela aura un impact sur les performances

12
Tarun

Lodash est également le même. Commencez par écrire un script comme suit:

<script type="text/template" id="genTable">
<table cellspacing='0' cellpadding='0' border='1'>
        <tr>
            <% for(var prop in users[0]){%>
            <th><%= prop %> </th>
            <% }%>
        </tr>
        <%_.forEach(users, function(user) { %>
            <tr>
                 <% for(var prop in user){%>
                    <td><%= user[prop] %> </td>
                <% }%>

            </tr>
        <%})%>
</table>

Maintenant, écrivez quelques JS simples comme suit:

var arrOfObjects = [];
for (var s = 0; s < 10; s++) {
    var simpleObject = {};
    simpleObject.Name = "Name_" + s;
    simpleObject.Address = "Address_" + s;
    arrOfObjects[s] = simpleObject;
}
var theObject = { 'users': arrOfObjects }
var compiled = _.template($("#genTable").text());
var sigma = compiled({ 'users': myArr });

$(sigma).appendTo("#popup");

Où popoup est un div où vous voulez générer la table

1
Dr.Sai