Wie verwende ich underscore.js als Template-Engine?

262

Ich versuche, etwas über die neue Verwendung von Javascript als serverseitige Sprache und als funktionale Sprache zu lernen. Vor ein paar Tagen habe ich von node.js und Express Framework gehört. Dann sah ich underscore.js als eine Reihe von Dienstprogrammfunktionen. Ich habe diese Frage beim Stackoverflow gesehen . Es heißt, wir können underscore.js als Template-Engine verwenden. Jeder kennt gute Tutorials darüber, wie man underscore.js für Vorlagen verwendet, insbesondere für Biginner, die weniger Erfahrung mit fortgeschrittenem Javascript haben. Vielen Dank

Knodumi
quelle
12
In "Lukes" Verteidigung hatte die verbesserte Version des Handbuchs mindestens schon im Mai keine fortgeschrittene Verwendung
Shanimal
Ich habe gerade eine ähnliche Frage beantwortet, von der auch Ihre Frage profitieren würde. stackoverflow.com/questions/28136101/retrieve-column-in-parse/…
jeffdill2

Antworten:

475

Alles , was Sie über Strich Vorlage wissen müssen , ist hier . Nur 3 Dinge zu beachten:

  1. <% %> - um Code auszuführen
  2. <%= %> - um einen Wert in der Vorlage zu drucken
  3. <%- %> - um einige Werte zu drucken, ist HTML entkommen

Das ist alles.

Einfaches Beispiel:

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

dann tpl({foo: "blahblah"})würde auf die Zeichenfolge gerendert<h1>Some text: blahblah</h1>

EINSTELLEN
quelle
55
Ich verstehe nicht, warum irgendjemand dies ablehnen würde, es ist die kanonische Antwort und verweist auf die Anweisungen auf der Homepage des Projekts, es ist der Klassiker "Bringe einem Mann das Fischen bei".
Jon z
1
Ich denke, sie würden abstimmen, weil die von ihnen bereitgestellte Dokumentation nur sehr wenig darüber aussagt, wie <% und <% = über ihr einzigartiges Beispiel hinaus gemischt werden sollen und wie der Wechsel von <% = zu print () dieses Muster ändert. Auch bei der Verwendung von 'Interpolieren' gibt es einige merkwürdige Verhaltensweisen, die die Szene wahrscheinlich etwas erklärender machen würden. Auch das ist nicht vorgesehen. Obwohl ich zustimme, ist es eine dumme Sache, darüber abzustimmen.
QueueHammer
8
3. <% -%> - um einige Werte mit HTML-
Escape
13
Ich habe nicht abgelehnt, aber Ihre Antwort erklärt (abgesehen vom Anbieten eines Links) nicht, wie underscore.js als Vorlagen-Engine verwendet wird. Ihre Antwort bietet einen schnellen "Spickzettel", vielleicht für diejenigen, die ihn bereits erhalten, aber für sich genommen ist er keine Antwort auf die Frage. Ich bin überrascht, dass es so viele positive Stimmen hat wie es.
Zach Lysobey
1
-1 ist die Dokumentation in vielerlei Hinsicht mangelhaft. Es ist fast sicher, dass der Benutzer nach Konsultation der Dokumente hierher gekommen ist. Schlechte Antwort.
Matt Parkins
198
<!-- 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 Danke @PHearst!
  • JsFiddle (aktuell)
  • JsFiddle- Liste gruppiert nach Anfangsbuchstaben (komplexes Beispiel mit Bildern, Funktionsaufrufen, Untervorlagen) viel Spaß ...
  • JsFiddle Demo von XSS Hack von @tarun_telang unten notiert
  • JsFiddle Eine nicht standardmäßige Methode zum Erstellen von Untervorlagen
Shanimal
quelle
17
Vielen Dank, dass Sie das Skript-Tag "text / html" in Ihrem Beispiel explizit verwendet haben. Ich bin neu bei underscore.js und habe die Dokumentation unglücklicherweise falsch gelesen. Es ist schön zu wissen, dass templateString nicht immer inline geschrieben werden muss.
Aschyiel
Die Vorlage ist nicht wirklich text/htmlso, dass das Sagen type="text/html"eine Lüge ist, Lügen können Probleme verursachen. Mit einem genauen Typ wie z text/x-underscore.
Mu ist zu kurz
6
mu, ich denke es ist gut darauf hinzuweisen, dass es keine Rolle spielt. Seien wir ehrlich, alles, was Sie dort ablegen, ist eine Lüge. text / x-underscore ist eine größere Lüge, weil ich lodash benutze, lol :) In der letzten JsFiddle habe ich hinzugefügt, type="foo/bar"weil ich möchte, dass jeder weiß, dass es keine Rolle spielt, solange der Browser / Server es nicht erkennt und versucht etwas damit zu tun. Da HTML keine Art von Skript ist, fühle ich mich ziemlich sicher mit Text / HTML (John Resig verwendet es). Foo / Bar funktioniert auch :)
Shanimal
4
Die Leute sind die ganze Zeit anderer Meinung als ich. Ich gebe mein Bestes, um es nicht persönlich zu nehmen (auch wenn es persönlich ist :). Ich bin immer und immer wieder von unbeabsichtigten Nebenwirkungen kleiner Schlamperei verbrannt worden, daher ist es meine Gewohnheit, dass es auf der Seite der Strenge liegt. Die MIME-Typspezifikationen reservieren tatsächlich */x-*Typen für " erfundene " Zwecke. Ich glaube nicht, dass es einen text/underscoreTyp in den offiziellen Registern gibt, also verwende ich ihn, text/x-underscoreweil ich paranoid bin und sie wirklich darauf aus sind, mich zu kriegen.
Mu ist zu kurz
1
Lassen Sie es
wissen,
94

In der einfachsten Form würden Sie es wie folgt verwenden:

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

Wenn Sie eine Vorlage einige Male verwenden, möchten Sie sie kompilieren, damit sie schneller ist:

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

Ich persönlich bevorzuge die Syntax im Moustache-Stil. Sie können die Vorlagenmarker-Markierungen anpassen, um doppelte geschweifte Klammern zu verwenden:

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

var template = _.template('<li>{{ name }}</li>');
böser Schmuck
quelle
Der Tipp zur Schnurrbartinterpolation hat mir bei der Verwendung der Express3-Ansicht geholfen, die mit ejs gerendert wurde. Vielen Dank!
Micrub
Um Vorlagen aus der Ansicht zu verwenden, können Sie Folgendes in Ihrem Seiten-Markup verwenden: <script type = "text / template" id = "my-template"> <div> <% - name%> </ div> </ script > und führen Sie dann in Ihrem JS Folgendes aus: var html = _.template ($ ('# my-template'). html (), {name: "John Smith"});
Gaurav Gupta
2
@evilcelery - Ihr interpolateTipp hat nicht funktioniert, aber dies hat:_.templateSettings = { interpolate: /\{\{\=(.+?)\}\}/g, escape: /\{\{\-(.+?)\}\}/g, evaluate: /\{\{(.+?)\}\}/g };
vsync
28

Die Dokumentation zum Templating ist teilweise, ich habe mir die Quelle angesehen.

Die Funktion _.template hat 3 Argumente:

  1. String Text : die Vorlage Zeichenfolge
  2. Objektdaten : die Bewertungsdaten
  3. Objekteinstellungen : lokale Einstellungen, die _.templateSettings ist die globalen Einstellungen Objekt

Wenn keine Daten (oder Null) angegeben werden, wird eine Renderfunktion zurückgegeben. Es hat 1 Argument:

  1. Objektdaten : selber wie die Daten über

Es gibt 3 Regex-Muster und 1 statischen Parameter in den Einstellungen:

  1. RegExp- Auswertung : "<% code%>" in der Vorlagenzeichenfolge
  2. RegExp- Interpolation : "<% = Code%>" in der Vorlagenzeichenfolge
  3. RegExp- Escape : "<% - Code%>"
  4. String - Variable : optional, der Name des Daten Parameter in der Vorlage Zeichenfolge

Der Code in einem Bewertungsabschnitt wird einfach ausgewertet. Sie können der ausgewerteten Vorlage eine Zeichenfolge aus diesem Abschnitt mit dem Befehl __p + = "mystring" hinzufügen. Dies wird jedoch nicht empfohlen (nicht Teil der Vorlagenschnittstelle). Verwenden Sie stattdessen den Interpolationsabschnitt. Diese Art von Abschnitt dient zum Hinzufügen von Blöcken wie if oder for zur Vorlage.

Das Ergebnis des Codes im Interpolationsabschnitt wird der ausgewerteten Vorlage hinzugefügt. Wenn null zurückgegeben wird, wird eine leere Zeichenfolge hinzugefügt.

Der Escape- Abschnitt maskiert HTML mit _.escape für den Rückgabewert des angegebenen Codes. So sein ähnlich als ein _.escape (Code) in einem Interpolations - Abschnitt, aber es entkommt mit \ den Zeichen wie Leerzeichen \ n bevor er den Code an die gibt _.escape . Ich weiß nicht, warum das so wichtig ist, es steht im Code, aber es funktioniert gut mit der Interpolation und _.escape - was den Leerzeichen nicht entgeht - auch.

Standardmäßig wird die Daten wird der Parameter durch eine bestandene mit (Daten) {...} Aussage, aber diese Art der Auswertung ist viel langsamer als der mit dem Namen Variable auswertet. Die Daten mit dem Variablenparameter zu benennen ist also etwas Gutes ...

Beispielsweise:

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

Ergebnisse

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"

Weitere Beispiele zur Verwendung der Vorlage und zum Überschreiben der Standardeinstellungen finden Sie hier: http://underscorejs.org/#template

Beim Laden von Vorlagen haben Sie viele Optionen, aber am Ende müssen Sie die Vorlage immer in eine Zeichenfolge konvertieren. Sie können es wie im obigen Beispiel als normale Zeichenfolge angeben oder es aus einem Skript-Tag laden und die .html () -Funktion von jquery verwenden, oder Sie können es aus einer separaten Datei mit dem tpl-Plugin von require.js laden .

Eine weitere Option, um den Dom-Baum mit Laconic zu erstellen, anstatt Vorlagen zu erstellen .

inf3rno
quelle
21

Ich gebe ein sehr einfaches Beispiel

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

Das Ergebnis wäre

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

2) Dies ist eine Vorlage

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

Das ist HTML

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

Dies ist der Javascript-Code, der das JSON-Objekt enthält und die Vorlage in HTML einfügt

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

dinesh_malhotra
quelle
14

Mit Express ist es so einfach. Sie müssen lediglich das Konsolidierungsmodul auf dem Knoten verwenden, damit Sie es installieren können:

npm install consolidate --save

Dann sollten Sie die Standard-Engine folgendermaßen in eine HTML-Vorlage ändern:

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

Registrieren Sie die Unterstrich-Vorlagen-Engine für die HTML-Erweiterung:

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

es ist fertig !

Laden Sie nun zum Beispiel eine Vorlage namens 'index.html':

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

Möglicherweise müssen Sie das Unterstrichmodul installieren.

npm install underscore --save

Ich hoffe das hat dir geholfen!

Khalid Ahmada
quelle
12

Ich wollte noch eine wichtige Erkenntnis teilen.

Die Verwendung von <% = variable => würde zu einer Sicherheitsanfälligkeit bezüglich Cross-Site-Scripting führen. Daher ist es sicherer, stattdessen <% - variable -> zu verwenden.

Wir mussten <% = durch <% ersetzen, um Cross-Site-Scripting-Angriffe zu verhindern. Ich bin mir nicht sicher, ob dies Auswirkungen auf die Leistung hat

Tarun
quelle
2
+1 Ich habe meinem Beispiel einen Hinweis zu XSS hinzugefügt. Dies ist ein wirklich guter Punkt, um nicht bereinigte Benutzerinformationen in eine Webseite einzufügen. entweder über eine Template-Engine oder sogar $ .html ().
Shanimal
1

Lodash ist auch das gleiche. Schreiben Sie zuerst ein Skript wie folgt:

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

Schreiben Sie nun einige einfache JS wie folgt:

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

Wobei popoup ein div ist, in dem Sie die Tabelle generieren möchten

Dr.Sai
quelle