Come utilizzare underscore.js come motore di template?


262

Sto cercando di conoscere nuovi usi di javascript come lingua lato server e come lingua funzionale. Qualche giorno fa ho sentito parlare di node.js e di express framework. Poi ho visto su underscore.js come un insieme di funzioni di utilità. Ho visto questa domanda su StackOverflow . Dice che possiamo usare underscore.js come motore di template. qualcuno conosce buoni tutorial su come usare underscore.js per il templating, specialmente per i principianti che hanno meno esperienza con javascript avanzato. Grazie


12
Nella difesa di "Luke", la versione migliorata del manuale almeno già a maggio non aveva un uso avanzato
Shanimal

Ho appena risposto a una domanda simile che avrebbe giovato anche alla tua domanda. stackoverflow.com/questions/28136101/retrieve-column-in-parse/...
jeffdill2

Risposte:


475

Tutto quello che devi sapere sul modello di sottolineatura è qui . Solo 3 cose da tenere a mente:

  1. <% %> - per eseguire un po 'di codice
  2. <%= %> - per stampare un valore nel modello
  3. <%- %> - per stampare alcuni valori HTML fuggiti

Questo è tutto.

Esempio semplice:

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

quindi tpl({foo: "blahblah"})verrebbe eseguito il rendering sulla stringa<h1>Some text: blahblah</h1>


55
Non capisco perché qualcuno dovrebbe sottovalutare questo, è la risposta canonica e indica le istruzioni sulla homepage del progetto, è il classico "insegnare a un uomo a pescare".
Jon z,

1
Penso che voterebbero in basso perché la documentazione che forniscono non fornisce molto su come mescolare <% e <% = al di là del loro esempio singolare e su come passare da <% = a print () cambi quel modello. Inoltre quando si usa "interpolare" ci sono alcuni comportamenti strani che probabilmente renderebbero la scena con un po 'più di spiegazione. Ancora una volta, che non viene fornito. Anche se sono d'accordo, è una cosa stupida votare in fondo.
QueueHammer,

8
3. <% -%> - per stampare alcuni valori con HTML sfuggito
LeeGee

13
Non ho votato in negativo, ma la tua risposta non fa nulla (oltre a offrire un link) per spiegare come utilizzare underscore.js come motore di template. La tua risposta fornisce un rapido "cheat sheet" forse per coloro che già lo ottengono, ma di per sé non è una risposta alla domanda. Sono sorpreso che abbia tanti voti quanti ne abbia.
Zach Lysobey,

1
-1, la documentazione è carente sotto molti aspetti. È quasi certo che l'utente sia venuto qui dopo aver consultato i documenti. Risposta scadente
Matt Parkins

199
<!-- 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 Grazie @PHearst!
  • JsFiddle (più recente)
  • Elenco JsFiddle raggruppato per prima lettera (esempio complesso con immagini, chiamate di funzioni, sotto-modelli). divertiti ...
  • Demo JsFiddle dell'hack XSS notato da @tarun_telang di seguito
  • JsFiddle Un metodo non standard per eseguire modelli secondari

17
Grazie per aver esplicitamente utilizzato il tag di script "text / html" nel tuo esempio; Sono nuovo di underscore.js e ho erroneamente letto male la documentazione - è bello sapere che templateString non deve sempre essere scritto in linea.
aschyiel,

Il modello non è in realtà text/htmlquindi dicendo che type="text/html"è una bugia, le bugie possono causare problemi. Staresti meglio con un tipo preciso come text/x-underscore.
mu è troppo corto il

6
mu, penso che sia bene sottolineare che non importa. ammettiamolo, qualsiasi cosa tu metta lì è una bugia. text / x-underscore è una bugia più grande perché uso lodash, lol :) Nell'ultimo JsFiddle ho aggiunto type="foo/bar"perché voglio che tutti sappiano che non importa finché il browser / server non lo riconosce e prova per farci qualcosa. Dato che html non è un tipo di script, mi sento abbastanza sicuro con text / html (John Resig lo usa) funziona anche foo / bar :)
Shanimal,

4
Le persone non sono sempre d'accordo con me, faccio del mio meglio per non prenderlo sul personale (anche quando è personale :). Sono stato bruciato da effetti collaterali involontari di lieve trascuratezza più e più volte, quindi la mia abitudine è quella di sbagliare dal lato della rigidità. Le specifiche del tipo MIME in realtà riservano */x-*tipi per usi "inventati", non penso che ci sia un text/underscoretipo nei registri ufficiali, quindi lo uso text/x-underscoreperché sono paranoico e sono davvero pronti a prendermi.
mu è troppo corto l'

1
fa sapere che la demo XSS non funziona più perché i browser si rifiutano di eseguire JS con un
mimetype

94

Nella sua forma più semplice lo useresti come:

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

Se utilizzerai un modello alcune volte, dovrai compilarlo in modo che sia più veloce:

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

Personalmente preferisco la sintassi in stile Moustache. È possibile regolare i marcatori token modello per utilizzare le parentesi graffe doppie:

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

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

Il suggerimento sull'interpolazione dei baffi mi ha aiutato durante l'utilizzo della vista express3 resa tramite ejs. Grazie!
Micrub

Per utilizzare i modelli dalla vista, è possibile avere quanto segue nel markup della pagina: <script type = "text / template" id = "my-template"> <div> <% - name%> </div> </ script > e quindi procedi come segue nel tuo JS: var html = _.template ($ ('# my-template'). html (), {name: "John Smith"});
Gaurav Gupta,

2
@evilcelery - il tuo interpolatesuggerimento non ha funzionato, ma questo ha funzionato:_.templateSettings = { interpolate: /\{\{\=(.+?)\}\}/g, escape: /\{\{\-(.+?)\}\}/g, evaluate: /\{\{(.+?)\}\}/g };
vsync

28

La documentazione per il templating è parziale, ho visto la fonte.

La funzione _.template ha 3 argomenti:

  1. Testo stringa : la stringa del modello
  2. Dati oggetto : i dati di valutazione
  3. Impostazioni oggetto : impostazioni locali, _.templateSettings è l'oggetto impostazioni globali

Se non viene fornito alcun dato (o null), verrà restituita una funzione di rendering . Ha 1 argomento:

  1. Dati oggetto : stessi dei dati sopra

Ci sono 3 modelli regex e 1 parametro statico nelle impostazioni:

  1. RegExp valuta : "<% code%>" nella stringa del modello
  2. Interpolazione RegExp : "<% = code%>" nella stringa del modello
  3. Regexp sfuggire : "<% - code%>"
  4. Variabile stringa : facoltativo, il nome del parametro dati nella stringa modello

Il codice in una sezione di valutazione verrà semplicemente valutato. Puoi aggiungere una stringa da questa sezione con il comando __p + = "mystring" al modello valutato, ma questo non è raccomandato (non fa parte dell'interfaccia di template), usa invece la sezione interpolate. Questo tipo di sezione serve per aggiungere blocchi come if o for al template.

Il risultato del codice nella sezione interpolata verrà aggiunto al modello valutato. Se restituito null, verrà aggiunta una stringa vuota.

La sezione escape sfugge a html con _.escape sul valore restituito di un determinato codice. Quindi è simile a un _.escape (codice) in una sezione interpolata , ma sfugge a \ gli spazi bianchi come \ n prima di passare il codice a _.escape . Non so perché sia ​​così importante, è nel codice, ma funziona bene con l' interpolato e _.escape - che non sfugge anche ai caratteri dello spazio bianco -.

Per impostazione predefinita, il parametro data viene passato da un'istruzione with (data) {...} , ma questo tipo di valutazione è molto più lento rispetto alla valutazione con variabile denominata. Quindi nominare i dati con il parametro variabile è qualcosa di buono ...

Per esempio:

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);

risultati

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"

Puoi trovare qui altri esempi su come utilizzare il modello e sovrascrivere le impostazioni predefinite: http://underscorejs.org/#template

Con il caricamento del modello hai molte opzioni, ma alla fine devi sempre convertire il modello in stringa. Puoi assegnarlo come una normale stringa come nell'esempio precedente, oppure puoi caricarlo da un tag script e utilizzare la funzione .html () di jquery, oppure puoi caricarlo da un file separato con il plug-in tpl di require.js .

Un'altra opzione per costruire l'albero del dom con laconic invece che con il modello.


21

Sto dando un esempio molto semplice

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); 

Il risultato sarebbe

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

2) Questo è un modello

   <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>

Questo è html

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

Questo è il codice javascript che contiene l'oggetto json e inserisce il modello in 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}));
  });


14

con express è così facile. tutto ciò che serve è utilizzare il modulo consolidato sul nodo, quindi è necessario installarlo:

npm install consolidate --save

quindi è necessario modificare il motore predefinito in modello html in questo modo:

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

registra il motore del modello di sottolineatura per l'estensione html:

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

E 'fatto !

Ora, ad esempio, carica un modello chiamato "index.html":

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

forse dovrai installare il modulo di sottolineatura.

npm install underscore --save

Spero che questo ti abbia aiutato!


12

Volevo condividere un'altra scoperta importante.

l'uso di <% = variabile => comporterebbe una vulnerabilità di scripting tra siti. Quindi è più sicuro usare <% - variabile -> invece.

Abbiamo dovuto sostituire <% = con <% - per prevenire attacchi di scripting tra siti. Non sono sicuro se questo avrà alcun impatto sulle prestazioni


2
+1 Ho aggiunto una nota su XSS al mio esempio. Questo è davvero un buon punto sull'iniezione di informazioni utente non autorizzate in una pagina web. tramite un motore modello o anche $ .html ().
Shanimal,

1

Lodash è anche lo stesso Prima di scrivere una sceneggiatura come segue:

<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>

Ora scrivi alcuni semplici JS come segue:

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");

Dove popoup è un div in cui si desidera generare la tabella

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.