Underscore.js bir şablon motoru olarak nasıl kullanılır?


262

Javascript'in sunucu dili ve işlevsel dil olarak yeni kullanımlarını öğrenmeye çalışıyorum. Birkaç gün önce node.js ve ekspres çerçeveyi duydum. Sonra underscore.js'yi bir dizi yardımcı fonksiyon olarak gördüm. Bu soruyu stackoverflow üzerinde gördüm . Bir şablon motoru olarak underscore.js'yi kullanabileceğimizi söylüyor. Herkes tempcore.js, özellikle gelişmiş javascript ile daha az deneyime sahip biginners için tempcore.js nasıl kullanılacağı hakkında iyi öğreticiler biliyor. Teşekkürler


12
"Luke'un" savunmasında, el kitabının en az Mayıs kadar erken geliştirilmiş sürümünde gelişmiş bir kullanımı yoktu
Shanimal

Sorunuza da fayda sağlayacak benzer bir soruyu yanıtladım. stackoverflow.com/questions/28136101/retrieve-column-in-parse/…
jeffdill2

Yanıtlar:


475

Alt çizgi şablonu hakkında bilmeniz gereken her şey burada . Akılda tutulması gereken sadece 3 şey:

  1. <% %> - kod çalıştırma
  2. <%= %> - şablonda bir değer yazdırmak için
  3. <%- %> - HTML'den kaçan bazı değerleri yazdırmak için

Hepsi bu kadar.

Basit bir örnek:

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

sonra tpl({foo: "blahblah"})dizeye dönüştürülür<h1>Some text: blahblah</h1>


55
Neden kimsenin buna karşı oy kullanacağını anlamıyorum , kanonik cevap ve projenin ana sayfasındaki talimatlara işaret ediyor, klasik "balık tutmayı öğret".
Jon z

1
Oy vermediklerini düşünüyorum, sağladıkları belgelerin <% ve <% = tekil örneklerinin ötesinde nasıl karıştırılacağı ve <% = 'den print ()' a geçişin bu kalıbı nasıl değiştirdiği konusunda çok az şey veriyorlar. Ayrıca 'enterpolat' kullanırken, muhtemelen biraz daha açıklama ile sahne yapacak bazı garip davranışlar vardır. Yine, sağlanmadı. Kabul etsem de, aptalca bir şey oylamayı düşürüyor.
QueueHammer

8
3. <% -%> - HTML
çıkışından

13
Oy vermedim, ancak cevabınız, bir şablon motoru olarak underscore.js'nin nasıl kullanılacağını açıklamak için hiçbir şey yapmıyor (bir bağlantı sunmanın yanı sıra). Cevabınız belki de zaten almış olanlar için hızlı bir "hile sayfası" sağlar, ancak kendi başına sorunun cevabı değildir. O kadar çok upvotes var şaşırdım.
Zach Lysobey

1
-1, dokümantasyon birçok açıdan eksiktir. Kullanıcının dokümanlar ile görüştükten sonra buraya geldiği neredeyse kesindir. Kötü cevap.
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 Teşekkürler @PHearst!
  • JSFiddle (en yeni)
  • JsFiddle Liste ilk harf (görüntüler, fonksiyon çağrıları, alt şablonlar w / karmaşık örnek) tarafından gruplandırılmış çatal! bir patlama var ...
  • Aşağıdaki @tarun_telang tarafından belirtilen XSS kesmek JsFiddle Demo
  • JsFiddle Alt şablonlar yapmak için standart olmayan bir yöntem

17
Örneğinizdeki "text / html" komut dosyası etiketini açıkça kullandığınız için teşekkür ederiz; Underscore.js'de yeniyim ve belgeleri mutsuzca yanlış okudum - templateString'in her zaman satır içi yazılması gerekmediğini bilmek güzel.
aschyiel

Şablon aslında değil text/htmlbunu söyleyerek type="text/html", yalan sorunlara bir yalan neden olabilir edilir. Gibi doğru bir tür ile daha iyi olurdu text/x-underscore.
mu çok kısa

6
Bence bunun önemli olmadığını belirtmek güzel. yüzleşelim, koyduğunuz her şey yalan. Lodash, lol kullandığım için text / x-underscore daha büyük bir yalan :) Son JsFiddle ekledim type="foo/bar"çünkü herkesin tarayıcı / sunucu tanımadığı ve denemediği sürece bunun önemli olmadığını bilmesini istiyorum onunla bir şeyler yapmak. Html bir tür komut dosyası olmadığından, metin / html (John Resig bunu kullanır) foo / bar da oldukça güvende hissediyorum :)
Shanimal

4
İnsanlar her zaman benimle aynı fikirde değil, kişisel olarak almamak için elimden geleni yapıyorum (kişisel olsa bile :). Küçük özensizliğin defalarca tekrar tekrar istenmeyen yan etkileriyle yakıldım, bu yüzden alışkanlığım katılık açısından yanılıyor. MIME türü özellikleri aslında */x-*"yapılmış" kullanımlar için türleri text/underscoreayırır, resmi kayıtlarda bir tür olduğunu düşünmüyorum, bu yüzden text/x-underscoreparanoyak olduğum için kullanıyorum ve gerçekten beni almaya geliyorlar.
mu çok kısa

1
tarayıcılar
JS'yi

94

En basit haliyle şöyle kullanabilirsiniz:

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

Bir şablonu birkaç kez kullanacaksanız, daha hızlı olacak şekilde derlemek istersiniz:

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

Şahsen bıyık tarzı sözdizimini tercih ediyorum. Şablon belirteci işaretleyicilerini çift kıvırcık ayraç kullanacak şekilde ayarlayabilirsiniz:

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

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

Bıyık enterpolasyon ipucu, ejs kullanarak oluşturulan express3 görünümünü kullanırken bana yardımcı oldu. Teşekkürler!
14'te

Görünümdeki şablonları kullanmak için sayfa işaretlemenizde aşağıdakilere sahip olabilirsiniz: <script type = "text / template" id = "my-template"> <div> <% - name%> </div> </ script > ve ardından JS'nizde aşağıdakileri yapın: var html = _.template ($ ('# my-template'). html (), {name: "John Smith"});
Gaurav Gupta

2
@evilcelery - interpolatebahşişiniz işe yaramadı, ancak bu işe yaradı:_.templateSettings = { interpolate: /\{\{\=(.+?)\}\}/g, escape: /\{\{\-(.+?)\}\}/g, evaluate: /\{\{(.+?)\}\}/g };
vsync

28

Şablonlama belgeleri kısmi, kaynağı izledim.

_.Template fonksiyonu 3 bağımsız değişkenler:

  1. Dize metni : şablon dizesi
  2. Nesne verileri : değerlendirme verileri
  3. Nesne ayarları : yerel ayarlar, _.templateSettings genel ayarlar nesnesidir

Hiçbir veri (veya null) verilmezse, oluşturma işlevi döndürülür. 1 argümanı vardır:

  1. Nesne verileri : yukarıdaki verilerle aynı

Ayarlarda 3 normal ifade deseni ve 1 statik parametre vardır:

  1. RegExp değerlendirmesi : şablon dizesinde "<% code%>"
  2. RegExp enterpolate : şablon dizesinde "<% = kod%>"
  3. RegExp kaçış : "<% - code%>"
  4. Dize değişkeni : isteğe bağlı, şablon dizesindeki veri parametresinin adı

Bir değerlendirme bölümündeki kod basit bir şekilde değerlendirilecektir. Bu bölümden , değerlendirilen şablona __p + = "mystring" komutuyla dize ekleyebilirsiniz , ancak bu önerilmez (şablonlama arabiriminin parçası değil), bunun yerine enterpolat bölümünü kullanın. Bu bölüm türü, şablona if veya for gibi bloklar eklemek içindir.

İnterpolat bölümündeki kodun sonucu , değerlendirilen şablona eklenir. Null değeri geri verilirse, boş dize eklenir.

Kaçış bölümü ile html kaçar _.escape verilen kod dönüş değeri üzerine. Bir daha onun benzeri Yani _.escape (kod) bir in aradeğer bölümünde, ancak birlikte kaçar \ benzeri boşluk karakteri \ n o kodu geçirmeden önce _.escape . Neden bu kadar önemli olduğunu bilmiyorum, kodda, ama interpolate ve _.escape - beyaz boşluk karakterleri kaçmaz - çok iyi çalışır.

Varsayılan olarak data parametresi bir (data) {...} deyimi tarafından iletilir , ancak bu tür bir değerlendirme adlandırılmış değişkenle değerlendirmeden çok daha yavaştır. Yani adlandırma verileri ile değişken parametre şey iyidir ...

Örneğin:

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

Sonuçlar

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"

Burada şablonun nasıl kullanılacağı ve varsayılan ayarların geçersiz kılınacağı ile ilgili daha fazla örnek bulabilirsiniz: http://underscorejs.org/#template

Şablon yükleme ile birçok seçeneğiniz vardır, ancak sonunda şablonu her zaman dizeye dönüştürmeniz gerekir. Yukarıdaki örnek gibi normal bir dize olarak verebilir veya bir komut dosyası etiketinden yükleyebilir ve jquery'nin .html () işlevini kullanabilir veya ayrı bir dosyadan requir.js tpl eklentisi ile yükleyebilirsiniz. .

Dom ağacını templating yerine laconic ile inşa etmek için başka bir seçenek .


21

Çok basit bir örnek veriyorum

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

Sonuç şu olurdu:

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

2) Bu bir şablon

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

Bu html

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

Bu, json nesnesini içeren ve şablonu html'ye yerleştiren javascript kodudur

   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

express ile çok kolay. tek ihtiyacınız düğümde birleştirme modülünü kullanmaktır, böylece onu kurmanız gerekir:

npm install consolidate --save

varsayılan motoru şu şekilde html şablonuyla değiştirmelisiniz:

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

html uzantısı için alt çizgi şablon motorunu kaydettirin:

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

bitti !

Şimdi yüklemek için örneğin 'index.html' adlı bir şablon:

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

belki alt çizgi modülünü kurmanız gerekir.

npm install underscore --save

Umarım bu sana yardımcı olmuştur!


12

Daha önemli bir bulguyu paylaşmak istedim.

<% = variable => kullanımı siteler arası komut dosyası oluşturma güvenlik açığına neden olur. Bunun yerine <% - değişken -> kullanmak daha güvenlidir.

Siteler arası komut dosyası saldırılarını önlemek için <% = yerine <% - ifadesini değiştirmek zorunda kaldık. Bunun performans üzerinde herhangi bir etkisi olup olmayacağından emin değilim


2
+1 Örneğime XSS hakkında bir not ekledim. Bu, onaylanmamış kullanıcı bilgilerinin bir web sayfasına enjekte edilmesi konusunda gerçekten iyi bir noktadır. bir şablon motoru veya hatta $ .html () yoluyla.
Shanimal

1

Lodash da aynıdır. İlk önce aşağıdaki gibi bir senaryo yazın:

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

Şimdi aşağıdaki gibi basit JS yazınız:

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

Popoup, tablo oluşturmak istediğiniz bir div olduğunda

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.