【问题标题】:How to use underscore.js as a template engine?如何使用 underscore.js 作为模板引擎?
【发布时间】:2011-06-14 07:31:41
【问题描述】:

我正在尝试了解 javascript 作为服务器端语言和函数式语言的新用法。几天前我听说了 node.js 和 express 框架。然后我看到了 underscore.js 作为一组实用函数。我看到了this question on stackoverflow 。它说我们可以使用 underscore.js 作为模板引擎。任何人都知道关于如何使用 underscore.js 进行模板的很好的教程,特别是对于那些对高级 javascript 经验较少的大佬。谢谢

【问题讨论】:

标签: javascript node.js functional-programming underscore.js template-engine


【解决方案1】:

你需要知道的关于下划线模板的一切都是here。只需要记住 3 件事:

  1. <% %> - 执行一些代码
  2. <%= %> - 在模板中打印一些值
  3. <%- %> - 打印一些 HTML 转义的值

就是这样。

简单示例:

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

然后tpl({foo: "blahblah"}) 将被渲染为字符串&lt;h1&gt;Some text: blahblah&lt;/h1&gt;

【讨论】:

  • 我不明白为什么有人会对此投反对票,这是 规范的答案并指向项目主页上的说明,这是经典的“教人”钓鱼”。
  • 我认为他们会投反对票,因为他们提供的文档几乎没有给出如何混合
  • 3. - 打印一些带有 HTML 转义的值
  • 我没有投反对票,但您的回答没有任何作用(除了提供链接)来解释如何使用 underscore.js 作为模板引擎。您的答案可能为那些已经得到它的人提供了一个快速的“备忘单”,但它本身并不是问题的答案。我很惊讶它有这么多的赞成票。
  • -1,文档在许多方面都存在缺陷。几乎可以肯定,用户是在查阅文档后来到这里的。不好的答案。
【解决方案2】:
<!-- 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 谢谢@PHearst!
  • JsFiddle(最新)
  • JsFiddle 按首字母分组的列表(带有图像、函数调用、子模板的复杂示例)fork 它!玩得开心...
  • JsFiddle 下面@tarun_telang 记录的 XSS hack 演示
  • JsFiddle 一种做子模板的非标准方法

【讨论】:

  • 感谢您在示例中明确使用“text/html”脚本标签;我是 underscore.js 的新手,很遗憾地误读了文档——很高兴知道 templateString 并不总是必须内联编写。
  • 模板实际上不是text/html 所以说type="text/html" 是谎言,谎言会导致问题。最好使用准确的类型,例如 text/x-underscore
  • mu,我认为指出这无关紧要是件好事。让我们面对现实吧,任何你放在那里的东西都是谎言。 text/x-underscore 是一个更大的谎言,因为我使用了 lodash,lol :) 在最后一个 JsFiddle 我添加了type="foo/bar" 因为我希望每个人都知道只要浏览器/服务器不识别它并不重要它并尝试用它做点什么。由于 html 不是一种脚本,我觉得 text/html 相当安全(John Resig 使用它) foo/bar 也可以:)
  • 人们总是不同意我的观点,我尽我所能不把它当作个人的(即使是个人的:)。我一次又一次地被轻微马虎的意外副作用烧伤,所以我的习惯是在严格方面犯错。 MIME 类型规范实际上保留了*/x-* 类型以供“虚构”使用,我认为官方注册表中没有text/underscore 类型,所以我使用text/x-underscore,因为我很偏执,他们真的很想找我。
  • 让我们知道 XSS 演示不再有效,因为浏览器拒绝执行具有错误 mimetype 的 JS
【解决方案3】:

以最简单的形式,您可以像这样使用它:

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

如果您要多次使用模板,您需要编译它以使其更快:

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

我个人更喜欢 Mustache 风格的语法。您可以调整模板标记标记以使用双花括号:

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

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

【讨论】:

  • Mustache 插值技巧在使用使用 ejs 渲染的 express3 视图时帮助了我。谢谢!
  • 要使用视图中的模板,您可以在页面标记中包含以下内容:
    然后在你的 JS 中执行以下操作: var html = _.template($('#my-template').html(), {name: "John Smith"});
  • @evilcelery - 你的interpolate 提示不起作用,但这样做:_.templateSettings = { interpolate: /\{\{\=(.+?)\}\}/g, escape: /\{\{\-(.+?)\}\}/g, evaluate: /\{\{(.+?)\}\}/g };
  • 【解决方案4】:

    模板的文档是部分的,我看了源码。

    _.template 函数有 3 个参数:

    1. String text:模板字符串
    2. 对象数据:评估数据
    3. 对象settings:本地设置,_.templateSettings是全局设置对象

    如果没有给出 data(或 null),则将返回 render 函数。它有 1 个参数:

    1. 对象data:同上面的data

    设置中有3个正则表达式模式和1个静态参数:

    1. RegExp 评估:模板字符串中的“”
    2. RegExp 插入:模板字符串中的“”
    3. 正则表达式 转义 : ""
    4. String variable:可选,模板字符串中data参数的名称

    evaluate 部分中的代码将被简单地评估。您可以使用 __p+="mystring" 命令将此部分中的字符串添加到评估的模板中,但不建议这样做(不是模板接口的一部分),请使用 interpolate 部分代替。这种类型的部分用于向模板添加 if 或 for 等块。

    interpolate 部分中的代码结果将添加到评估的模板中。如果返回 null,则添加空字符串。

    escape 部分在给定代码的返回值上使用 _.escape 对 html 进行转义。所以它与 interpolate 部分中的 _.escape(code) 相似,但它使用 \ 转义空格字符,如 \ n 在将代码传递给 _.escape 之前。我不知道为什么这很重要,它在代码中,但它与 interpolate_.escape 配合得很好 - 它不会逃避空白字符 - 也是。

    默认情况下 data 参数由 with(data){...} 语句传递,但是这种评估比使用命名的评估慢得多多变的。所以用 variable 参数命名 data 是件好事...

    例如:

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

    结果

    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"
    

    您可以在此处找到更多示例如何使用模板并覆盖默认设置: http://underscorejs.org/#template

    通过模板加载,您有很多选择,但最后您总是必须将模板转换为字符串。您可以像上面的示例一样将其作为普通字符串提供,或者您可以从脚本标签加载它,并使用 jquery 的 .html() 函数,或者您可以使用 tpl pluginrequire.jstpl plugin 从单独的文件加载它.

    另一个使用laconic而不是模板来构建dom树的选项。

    【讨论】:

      【解决方案5】:

      我举一个很简单的例子

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

      结果是

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

      2) 这是一个模板

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

      这是html

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

      这是包含 json 对象并将模板放入 html 的 javascript 代码

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

      【讨论】:

        【解决方案6】:

        使用 express 非常简单。您只需要在节点上使用 consolidate 模块,因此您需要安装它:

        npm install consolidate --save
        

        那么您应该通过以下方式将默认引擎更改为 html 模板:

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

        为html扩展注册下划线模板引擎:

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

        完成了!

        现在加载一个名为“index.html”的模板:

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

        也许你需要安装下划线模块。

        npm install underscore --save
        

        希望对你有所帮助!

        【讨论】:

          【解决方案7】:

          我想分享一个更重要的发现。

          使用 会导致跨站脚本漏洞。所以使用 更安全。

          我们必须将

          【讨论】:

          • +1 我在示例中添加了关于 XSS 的注释。这是关于将未经处理的用户信息注入网页的一个非常好的观点。通过模板引擎甚至 $.html()。
          【解决方案8】:

          Lodash 也是一样 先写一个脚本如下:

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

          现在写一些简单的JS如下:

          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 是你要在其中生成表格的 div

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-12-21
            • 1970-01-01
            • 2015-08-22
            • 1970-01-01
            • 2013-11-24
            相关资源
            最近更新 更多