Bagaimana cara menggunakan underscore.js sebagai mesin templat?


262

Saya mencoba mempelajari tentang penggunaan baru javascript sebagai bahasa serveride dan sebagai bahasa fungsional. Beberapa hari yang lalu saya mendengar tentang node.js dan framework express. Lalu saya melihat tentang underscore.js sebagai satu set fungsi utilitas. Saya melihat pertanyaan ini di stackoverflow . Dikatakan kita dapat menggunakan underscore.js sebagai mesin templat. ada yang tahu tutorial yang baik tentang cara menggunakan underscore.js untuk templating, terutama untuk biginners yang memiliki lebih sedikit pengalaman dengan javascript canggih. Terima kasih


12
Dalam pembelaan "Luke", versi manual yang diperbaiki setidaknya sedini Mei tidak memiliki penggunaan lanjutan
Shanimal

Saya baru saja menjawab pertanyaan serupa yang akan menguntungkan pertanyaan Anda juga. stackoverflow.com/questions/28136101/retrieve-column-in-parse/…
jeffdill2

Jawaban:


475

Semua yang perlu Anda ketahui tentang template garis bawah ada di sini . Hanya 3 hal yang perlu diingat:

  1. <% %> - untuk menjalankan beberapa kode
  2. <%= %> - untuk mencetak beberapa nilai dalam template
  3. <%- %> - untuk mencetak beberapa nilai HTML lolos

Itu saja.

Contoh sederhana:

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

maka tpl({foo: "blahblah"})akan diberikan ke string<h1>Some text: blahblah</h1>


55
Saya tidak mengerti mengapa ada orang yang turun-suara ini, itu adalah yang jawabannya kanonik dan poin untuk petunjuk pada homepage proyek, itu adalah klasik "mengajarkan seorang pria untuk ikan".
Jon z

1
Saya pikir mereka akan memilih karena dokumentasi yang mereka berikan memberi sangat sedikit dalam cara mencampur <% dan <% = di luar contoh tunggal mereka dan bagaimana beralih dari <% = untuk mencetak () mengubah pola itu. Juga ketika menggunakan 'interpolasi' ada beberapa perilaku aneh yang mungkin akan membuat heboh dengan sedikit lebih banyak penjelasan. Sekali lagi, yang tidak disediakan. Meskipun saya setuju, itu adalah hal yang bodoh.
QueueHammer

8
3. <% -%> - untuk mencetak beberapa nilai dengan HTML lolos
LeeGee

13
Saya tidak mengundurkan diri, tetapi jawaban Anda tidak melakukan apa pun (selain menawarkan tautan) untuk menjelaskan cara menggunakan underscore.js sebagai mesin templat. Jawaban Anda memberikan "lembar contekan" cepat mungkin bagi mereka yang sudah mendapatkannya, tetapi dengan sendirinya, itu bukan jawaban untuk pertanyaan itu. Saya kaget itu memiliki banyak upvotes seperti halnya.
Zach Lysobey

1
-1, dokumentasi kurang dalam banyak hal. Hampir pasti bahwa pengguna datang ke sini setelah berkonsultasi dengan dokumen. Jawaban yang buruk
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 Terima kasih @PHearst!
  • JsFiddle (terbaru)
  • Daftar JsFiddle dikelompokkan berdasarkan huruf pertama (contoh kompleks dengan gambar, panggilan fungsi, sub-templat) bercabang! semoga menyenangkan...
  • Demo JsFiddle dari hack XSS dicatat oleh @tarun_telang di bawah ini
  • JsFiddle Satu metode non-standar untuk melakukan sub-templat

17
Terima kasih telah menggunakan tag skrip "teks / html" secara eksplisit dalam contoh Anda; Saya baru di underscore.js dan saya tidak sengaja salah membaca dokumentasi - senang mengetahui templateString tidak selalu harus ditulis sebaris.
aschyiel

Template tidak benar-benar text/htmljadi mengatakan type="text/html"itu bohong, kebohongan dapat menyebabkan masalah. Anda akan lebih baik dengan tipe yang akurat seperti text/x-underscore.
mu terlalu pendek

6
mu, saya pikir itu baik untuk menunjukkan bahwa itu tidak masalah. hadapi saja, apa pun yang Anda taruh di sana adalah dusta. teks / x-garis bawah adalah kebohongan yang lebih besar karena saya menggunakan lodash, lol :) Di JsFiddle terakhir saya menambahkan type="foo/bar"karena saya ingin semua orang tahu bahwa itu tidak masalah asalkan browser / server tidak mengenalinya dan mencoba untuk melakukan sesuatu dengannya. Karena html bukan jenis skrip, saya merasa cukup aman dengan teks / html (John Resig menggunakannya) foo / bar juga berfungsi :)
Shanimal

4
Orang-orang tidak setuju dengan saya sepanjang waktu, saya melakukan yang terbaik untuk tidak menganggapnya pribadi (walaupun itu bersifat pribadi :). Saya telah dibakar oleh efek samping yang tidak disengaja dari kecerobohan kecil berulang-ulang sehingga kebiasaan saya adalah keliru di sisi ketat. Spesifikasi tipe MIME sebenarnya mencadangkan */x-*tipe untuk penggunaan "buatan", saya tidak berpikir ada text/underscoretipe dalam pendaftar resmi jadi saya menggunakan text/x-underscorekarena saya paranoid dan mereka benar-benar keluar untuk mendapatkan saya.
mu terlalu pendek

1
biarkan diketahui bahwa demo XSS tidak lagi berfungsi karena browser menolak untuk mengeksekusi JS dengan mimetype yang salah
nickford

94

Dalam bentuk yang paling sederhana, Anda akan menggunakannya seperti:

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

Jika Anda akan menggunakan template beberapa kali, Anda ingin mengompilasinya sehingga lebih cepat:

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

Saya pribadi lebih suka sintaks gaya Kumis. Anda dapat menyesuaikan penanda token template untuk menggunakan kurung kurawal ganda:

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

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

Tip interpolasi kumis membantu saya saat menggunakan tampilan express3 yang dirender menggunakan ejs. Terima kasih!
micrub

Untuk menggunakan templat dari tampilan, Anda dapat memiliki yang berikut di markup halaman Anda: <script type = "text / template" id = "my-templat"> <div> <% - name%> </div> </ script > dan kemudian lakukan hal berikut di JS Anda: var html = _.template ($ ('# my-templat'). html (), {name: "John Smith"});
Gaurav Gupta

2
@evilcelery - interpolatetip Anda tidak berfungsi, tetapi ini berhasil:_.templateSettings = { interpolate: /\{\{\=(.+?)\}\}/g, escape: /\{\{\-(.+?)\}\}/g, evaluate: /\{\{(.+?)\}\}/g };
vsync

28

Dokumentasi untuk templating sebagian, saya memperhatikan sumbernya.

Fungsi _.template memiliki 3 argumen:

  1. Teks string : string template
  2. Objek data : data evaluasi
  3. Objek pengaturan : pengaturan lokal, yang _.templateSettings adalah pengaturan global keberatan

Jika tidak ada data (atau nol) yang diberikan, maka fungsi render akan dikembalikan. Ada 1 argumen:

  1. Obyek Data : sama dengan data yang di atas

Ada 3 pola regex dan 1 parameter statis dalam pengaturan:

  1. Evaluasi RegExp : "<% code%>" dalam string template
  2. RegExp interpolasi : "<% = code%>" dalam string template
  3. RegExp escape : "<% - code%>"
  4. Variabel string : opsional, nama parameter data dalam string templat

Kode dalam mengevaluasi bagian akan hanya dievaluasi. Anda dapat menambahkan string dari bagian ini dengan perintah __p + = "mystring" ke templat yang dievaluasi, tetapi ini tidak disarankan (bukan bagian dari antarmuka templating), gunakan bagian interpolasi alih-alih itu. Jenis bagian ini untuk menambahkan blok seperti jika atau untuk templat.

Hasil kode di bagian interpolasi akan ditambahkan ke templat yang dievaluasi. Jika null diberikan kembali, maka string kosong akan ditambahkan.

Bagian melarikan diri lolos dari html dengan _.escape pada nilai kembali dari kode yang diberikan. Jadi mirip dengan _.escape (kode) di bagian interpolasi , tetapi ia lolos dengan \ karakter spasi seperti \ n sebelum melewati kode ke _.escape . Saya tidak tahu mengapa itu penting, ada dalam kode, tetapi ia bekerja dengan baik dengan interpolasi dan _.escape - yang tidak luput dari karakter white-space - juga.

Secara default parameter data dilewatkan oleh pernyataan with (data) {...} , tetapi jenis evaluasi ini jauh lebih lambat daripada evaluasi dengan variabel bernama. Jadi penamaan data dengan parameter variabel adalah sesuatu yang baik ...

Sebagai contoh:

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

hasil

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"

Anda dapat menemukan lebih banyak contoh di sini tentang cara menggunakan templat dan mengabaikan pengaturan default: http://underscorejs.org/#template

Dengan memuat template Anda memiliki banyak pilihan, tetapi pada akhirnya Anda selalu harus mengubah template menjadi string. Anda dapat memberikannya sebagai string normal seperti contoh di atas, atau Anda dapat memuatnya dari tag skrip, dan menggunakan fungsi .html () dari jquery, atau Anda dapat memuatnya dari file terpisah dengan plugin tpl dari require.js .

Pilihan lain untuk membangun pohon dom dengan laconic bukan templating.


21

Saya memberikan contoh yang sangat sederhana

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

Hasilnya adalah

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

2) Ini adalah templat

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

Ini html

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

Ini adalah kode javascript yang berisi objek json dan menempatkan template ke 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

dengan express sangat mudah. semua yang Anda butuhkan adalah menggunakan modul konsolidasi pada node sehingga Anda perlu menginstalnya:

npm install consolidate --save

maka Anda harus mengubah mesin default ke template html dengan ini:

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

daftarkan mesin template garis bawah untuk ekstensi html:

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

selesai !

Sekarang untuk memuat misalnya template yang disebut 'index.html':

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

mungkin Anda perlu menginstal modul garis bawah.

npm install underscore --save

Saya harap ini membantu Anda!


12

Saya ingin berbagi satu temuan penting lagi.

penggunaan <% = variabel => akan menghasilkan kerentanan skrip lintas situs. Jadi lebih aman menggunakan <% - variabel -> sebagai gantinya.

Kami harus mengganti <% = dengan <% - untuk mencegah serangan skrip lintas situs. Tidak yakin, apakah ini akan berdampak pada kinerja


2
+1 Saya menambahkan catatan tentang XSS ke contoh saya. Ini adalah poin yang sangat bagus tentang menyuntikkan informasi pengguna yang tidak bersih ke halaman web. baik melalui mesin template atau bahkan $ .html ().
Shanimal

1

Lodash juga sama Pertama menulis skrip sebagai berikut:

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

Sekarang tulis beberapa JS sederhana sebagai berikut:

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

Di mana popoup adalah div di mana Anda ingin menghasilkan tabel

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.