Jak używać underscore.js jako silnika szablonów?


262

Próbuję dowiedzieć się o nowych zastosowaniach javascript jako języka serwera i języka funkcjonalnego. Kilka dni temu słyszałem o node.js i express framework. Potem zobaczyłem underscore.js jako zestaw funkcji narzędziowych. Widziałem to pytanie przy przepełnieniu stosu . Mówi, że możemy użyć underscore.js jako silnika szablonów. każdy zna dobre samouczki na temat korzystania z underscore.js do tworzenia szablonów, szczególnie dla biginnerów, którzy mają mniejsze doświadczenie z zaawansowanym javascript. Dzięki


12
W obronie „Luke'a” ulepszona wersja podręcznika przynajmniej w maju nie była zaawansowana
Shanimal

Właśnie odpowiedziałem na podobne pytanie, które również byłoby korzystne dla twojego pytania. stackoverflow.com/questions/28136101/retrieve-column-in-parse/…
jeffdill2

Odpowiedzi:


475

Wszystko, co musisz wiedzieć o szablonie podkreślenia, znajduje się tutaj . Pamiętaj tylko o 3 rzeczach:

  1. <% %> - aby wykonać kod
  2. <%= %> - aby wydrukować pewną wartość w szablonie
  3. <%- %> - aby wydrukować niektóre wartości, które uciekł HTML

To wszystko.

Prosty przykład:

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

następnie tpl({foo: "blahblah"})byłby renderowany do łańcucha<h1>Some text: blahblah</h1>


55
Nie rozumiem, dlaczego ktokolwiek miałby to głosować w dół, jest to odpowiedź kanoniczna i wskazuje instrukcje na stronie głównej projektu, jest to klasyczny „naucz człowieka łowienia”.
Jon z

1
Myślę, że odrzuciliby głosowanie, ponieważ dokumentacja, którą dostarczają, daje niewiele, jak mieszać <% i <% = poza ich pojedynczym przykładem i jak przejście z <% = na print () zmienia ten wzorzec. Również przy użyciu interpolacji występują dziwne zachowania, które prawdopodobnie stworzyłyby scenę z nieco większym wyjaśnieniem. Znowu, co nie jest przewidziane. Chociaż się zgadzam, to głupie zlekceważenie.
QueueHammer

8
3. <% -%> - aby wydrukować niektóre wartości ze
znakiem

13
Nie przegłosowałem, ale twoja odpowiedź nic nie robi (oprócz oferowania linku), aby wyjaśnić, jak używać underscore.js jako silnika szablonów. Twoja odpowiedź stanowi szybki „ściągawka”, być może dla tych, którzy już ją otrzymali, ale sama w sobie nie jest odpowiedzią na pytanie. Jestem zaskoczony, że ma tyle głosów poparcia, co ma.
Zach Lysobey

1
-1, dokumentacja jest pod wieloma względami wadliwa. Jest prawie pewne, że użytkownik przyszedł tutaj po konsultacji z dokumentami. Słaba odpowiedź.
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 Thanks @PHearst!
  • JsFiddle (najnowszy)
  • JsFiddle Lista pogrupowana według pierwszej litery (złożony przykład z obrazami, wywołania funkcji, pod-szablony) rozwidlamy! świetnie się bawić...
  • Demo JsFiddle dotyczące hackowania XSS odnotowane przez @tarun_telang poniżej
  • JsFiddle Jedna niestandardowa metoda wykonywania pod-szablonów

17
Dziękujemy za jawne użycie tagu skryptowego „text / html” w twoim przykładzie; Jestem nowy w underscore.js i niefortunnie źle przeczytałem dokumentację - miło jest wiedzieć, że szablonString nie zawsze musi być napisany w wierszu.
aschyiel,

Szablon nie jest text/htmltak type="text/html"kłamliwy, kłamstwa mogą powodować problemy. Lepiej byłoby z dokładnym typem, takim jak text/x-underscore.
mu jest za krótki

6
mu, myślę, że dobrze jest zaznaczyć, że to nie ma znaczenia. spójrzmy prawdzie w oczy, wszystko, co tam umieścisz, jest kłamstwem. tekst / x-podkreślenie jest większym kłamstwem, ponieważ używam lodash, lol :) W ostatnim JsFiddle dodałem, type="foo/bar"ponieważ chcę, aby wszyscy wiedzieli, że to nie ma znaczenia, dopóki przeglądarka / serwer nie rozpoznaje i nie próbuje coś z tym zrobić. Ponieważ html nie jest rodzajem skryptu, czuję się dość bezpiecznie z tekstem / html (używa go John Resig) foo / bar również działa :)
Shanimal

4
Ludzie cały czas się ze mną nie zgadzają, staram się nie brać tego osobiście (nawet jeśli jest to sprawa osobista :). Byłem palony przez niezamierzone skutki uboczne niewielkiej niechlujstwa w kółko, więc moim nawykiem jest błądzenie po stronie surowości. Specyfikacje typów MIME faktycznie rezerwują */x-*typy dla „wymyślonych” zastosowań, nie sądzę, że jest taki text/underscoretyp w oficjalnych rejestrach, więc używam, text/x-underscoreponieważ jestem paranoikiem i naprawdę chcą mnie dopaść.
mu jest za krótki

1
daj znać, że demo XSS już nie działa, ponieważ przeglądarki odmawiają wykonania JS z niepoprawnym
typem

94

W najprostszej formie możesz go użyć w następujący sposób:

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

Jeśli zamierzasz używać szablonu kilka razy, musisz go skompilować, aby był szybszy:

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

Osobiście wolę składnię stylu Wąsy. Możesz dostosować szablon znaczników tokenów, aby używać podwójnych nawiasów klamrowych:

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

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

Wskazówka dotycząca interpolacji wąsów pomogła mi podczas korzystania z widoku express3 renderowanego przy użyciu ejs. Dzięki!
micrub

Aby korzystać z szablonów z widoku, możesz mieć następujące znaczniki na stronie: <script type = "text / template" id = "my-template"> <div> <% - name%> </div> </ script >, a następnie wykonaj następujące czynności w JS: var html = _.template ($ ('# my-template'). html (), {name: "John Smith"});
Gaurav Gupta

2
@evilcelery - twój typ interpolatenie zadziałał, ale to _.templateSettings = { interpolate: /\{\{\=(.+?)\}\}/g, escape: /\{\{\-(.+?)\}\}/g, evaluate: /\{\{(.+?)\}\}/g };
zadziałało

28

Dokumentacja szablonów jest częściowa, obejrzałem źródło.

Funkcja _.template ma 3 argumenty:

  1. String tekst : ciąg szablon
  2. Dane obiektu : dane oceny
  3. Ustawienia obiektu : ustawienia lokalne, _.templateSettings to obiekt ustawień globalnych

Jeśli nie podano danych (lub null), funkcja renderowania zostanie zwrócona. Ma 1 argument:

  1. Dane obiektu : takie same jak powyższe dane

W ustawieniach są 3 wzorce wyrażeń regularnych i 1 parametr statyczny:

  1. RegExp ocenia : „<% code%>” w ciągu szablonu
  2. RegExp interpolate : "<% = code%>" w ciągu szablonu
  3. RegExp Escape : „<% - code%>”
  4. Zmienna ciąg : opcjonalnie nazwa parametru danych w ciągu szablonu

Kod w sekcji oceny zostanie po prostu oceniony. Możesz dodać ciąg z tej sekcji za pomocą polecenia __p + = "mystring" do ocenianego szablonu, ale nie jest to zalecane (nie jest częścią interfejsu szablonów), zamiast tego użyj sekcji interpolacji. Ten typ sekcji służy do dodawania bloków, takich jak if lub for, do szablonu.

Wynik kodu w sekcji interpolacji zostanie dodany do ocenianego szablonu. Jeśli zwrócona zostanie wartość null, zostanie dodany pusty ciąg.

Ucieczka sekcja ucieka html z _.escape na wartości zwracanej danego kodu. Jest więc podobny do _.escape (kod) w sekcji interpolacji , ale ucieka \ znakami spacji, takimi jak \ n, zanim przekaże kod do _.escape . Nie wiem, dlaczego to takie ważne, jest w kodzie, ale działa dobrze z interpolacją i _.escape - która nie ucieka również przed spacjami - również.

Domyślnie parametr data jest przekazywany przez instrukcję with (data) {...} , ale tego rodzaju ocena jest znacznie wolniejsza niż ocena z nazwaną zmienną. Tak nazywania danych ze zmiennym parametrem jest czymś dobrym ...

Na przykład:

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

wyniki

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"

Możesz znaleźć tutaj więcej przykładów korzystania z szablonu i zastąpienia ustawień domyślnych: http://underscorejs.org/#template

Wczytując szablon masz wiele opcji, ale na końcu zawsze musisz przekonwertować szablon na ciąg. Można podać go jako zwykłego łańcucha jak w przykładzie powyżej, lub można go załadować z tagu skrypt i użyć .html () funkcję jQuery, czy można załadować go z oddzielnego pliku z TPL wtyczki z require.js .

Inna opcja, aby zbudować drzewo dom lakoniczne zamiast szablonów.


21

Podaję bardzo prosty przykład

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

Wynik byłby

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

2) To jest szablon

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

To jest HTML

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

To jest kod javascript, który zawiera obiekt Json i umieszczenie szablonu w 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

z ekspresowym to takie proste. wystarczy użyć modułu konsolidacyjnego w węźle, aby go zainstalować:

npm install consolidate --save

następnie powinieneś zmienić domyślny silnik na szablon HTML tak:

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

zarejestruj silnik szablonu podkreślenia dla rozszerzenia HTML:

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

zrobione !

Teraz na przykład załaduj szablon o nazwie „index.html”:

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

być może będziesz musiał zainstalować moduł podkreślenia.

npm install underscore --save

Mam nadzieję, że to ci pomogło!


12

Chciałem podzielić się jeszcze jednym ważnym odkryciem.

użycie <% = zmienna => spowodowałoby powstanie luki w skryptach krzyżowych. Dlatego bezpieczniej jest używać zamiast tego <% - zmienna ->.

Musieliśmy zamienić <% = na <% - aby zapobiec atakom skryptowym między witrynami. Nie jestem pewien, czy będzie to miało wpływ na wydajność


2
+1 Dodałem notatkę o XSS do mojego przykładu. To naprawdę dobry punkt na temat wstrzykiwania niezarządzanych informacji o użytkowniku na stronę internetową. albo za pomocą silnika szablonów, a nawet $ .html ().
Shanimal,

1

Lodash jest również tym samym Najpierw napisz skrypt w następujący sposób:

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

Teraz napisz kilka prostych JS w następujący sposób:

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

Gdzie popoup to div, w której chcesz wygenerować stół

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.