【问题标题】:Run Template in Template (recursion) within underscore.js template engine在 underscore.js 模板引擎中的模板中运行模板(递归)
【发布时间】:2011-11-09 15:30:08
【问题描述】:

我正在使用backbone.js 和underscore.js 来构建一个javascript 应用程序。由于花费了数小时阅读并尝试在如下模板中运行模板,它变得越来越令人沮丧。

我的模板使用内置 underscore.js 模板引擎:

<script id="navigation_template" type="text/template">
  <div><%= title %>
      <% _.each(children, function(child) { %>
          <% render_this_template_recursively(child) %>
      <% }); %>
  </div>
</script>

我想为每个子元素( render_this_template_recursively(child) )呈现这个模板。

我该怎么做?

谢谢

【问题讨论】:

  • heeeeey,这是一个非常有趣的问题...您尝试以下答案了吗? ;)
  • 嘿亚当,你解决了吗?还是你用了别的东西?
  • @jamie-wilson 我从 Ashish Datta 的回答中得到了灵感。我在下面发布了一个简约的示例。

标签: javascript templates backbone.js underscore.js


【解决方案1】:

我没有亲自尝试过,但 _.template 返回一个函数(我将其命名为 templateFn 以强调这一点),因此您可以像这样将它传递给模板:

var templateFn = _.template($('#navigation_template').html());

$(this.el).html(templateFn({model: this.model, templateFn: templateFn}));

请注意,我正在传递整个模型(假设您的模型有一个 children 属性,该属性本身就是骨干模型的集合)并且您的模板将更改为:

<script id="navigation_template" type="text/template">
  <div><%= model.escape('title') %>
      <% _.each(model.children, function(child) { %>
          <%= templateFn(child, templateFn) %>
      <% }); %>
  </div>
</script>

祝你好运。我希望这对你有用

【讨论】:

  • @timDunham 如果我使用文本插件加载模板,我该怎么办。我应该做 templateFn = _.template($('#navigation_template').html());
  • &lt;%= templateFn(child, templateFn) %&gt; 不适合我。但效果很好&lt;%= templateFn({model: child, templateFn: templateFn}) %&gt;
【解决方案2】:

我刚刚成功地尝试了这个。我只用纯 UnderscoreJS 测试它,没有 BackboneJS 但在功能上应该没关系。

代码如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script type="text/javascript" src="underscore.js"></script>    
<style>

.container {
  position: relative;
  margin-bottom: 20px;
}

#container {
  position: relative;
  margin: auto;
}

.fib-box {
  position: absolute;
  top: 0px;
  left: 0px;
  background: rgba(0,68,242,0.15);
  border: 1px solid rgba(0,0,0,0.20); 
}

.header {
  padding-bottom: 10px;
}

</style>
  </head>
  <body> 

    <div class="header">
        <h3>Render Fibonacci With UnderscoreJS</h3>
        <form id="updateCount">
            <input type="text" value="13" id="fibSequence" />
            <input type="submit" value="Update" />
        </form>
    </div>

    <div class="container">
    <div id="container">

    </div>    
    </div>

<script type="text/template" id="template">
<% if(depth){ %>
<div class='fib-box' data-depth='<%= depth %>' style='width: <%= val %>px; height: <%= val %>px;'></div>
<% print(template(getFibObj(depth-1))) %>
<% } %>
</script>

<script type="text/javascript">

var template;

$(document).ready(function(){

    template = _.template($("#template").text());

    $("#updateCount").submit( function(){

        $("#container").html( template( getFibObj($("#fibSequence").val()) ) );

        var width = $("#container .fib-box:first").css("width");
        $("#container").css( {width: width, 'min-height': width} );

        return false;
    });

    $("#updateCount").submit();
});

function getFibObj(i){
    return {depth: i, val: fib(i)};
}

function fib(i){
    return ( i == 0 || i == 1 ) ? i : fib(i-1) + fib(i-2);
}

 </script>

  </body>
</html>

【讨论】:

  • @Ashish Datta 是否可以将这种方法与 viewmodel 之类的东西一起使用。像数据处理应该在视图模型中完成,然后将其传递给模板进行每次递归
  • @JSBin 不确定我是否 100% 关注,但您绝对可以在控制器中构建 HTML 块,然后将所有这些传递到您的模板中?
【解决方案3】:

我尝试使用 timDunham 和 Ates Goral 提供的示例,但它对我不起作用,因此我对其进行了一些升级。在下面找到它。

查看:

    template: _.template($("#tree").html()),

    render: function () {
        this.$el.html(this.template({
            options: this.collection.toJSON(),
            templateFn: this.template
        }));
    }

和模板:

<script type="text/template" id="tree">
<ul>
    <% _.each(options, function (node) { %>
        <li><%= node.title %></li>
        <% if (node.children) { %>
            <%= templateFn({ options: node.children, templateFn: templateFn }) %>
        <% } %>
    <% }); %>
</ul>

它对我来说效果很好。如您所见,主要区别在于将配置对象传递给 templateFn,而不是参数。希望你会发现它有用。

【讨论】:

  • 是否可以将此方法与视图模型之类的东西一起使用。像数据处理应该在视图模型中完成,然后将其传递给模板进行每次递归
【解决方案4】:

递归模板可能如下所示:

<ul>
    <% entries.forEach(function (entry) { %>
    <li>
        <%= entry.title %>
        <%
        if (entry.children) {
            print(tmpl({
                entries: entry.children,
                tmpl: tmpl
            }));
        }
        %>
    </li>
    <% }); %>
</ul>

首先,预编译您的模板:

entriesTmpl = _.template(entriesTmpl);

然后在传递您的数据和模板本身时调用它:

$el.html(entriesTmpl({
    entries: entryTree,
    tmpl: entriesTmpl
});

【讨论】:

    【解决方案5】:

    我最近使用骨干关系实现了这一点。我创建了一个小提琴,我认为如果你想看到一个可行的解决方案可能会有所帮助:http://jsfiddle.net/blaisco/ADKrK/

    我已经在下面发布了相关的内容。

    观点:

    var FolderView = Backbone.View.extend({
        el: $("#main"),
    
        template: _.template($("#folder-tmpl").html()),
    
        render: function () {
            this.$el.html(this.template({
                "folder": parentFolder.toJSON(),
                "templateFn": this.template
            }));
            return this;
        }
    });
    

    html/模板:

    <ul id="main"></ul>
    
    <script type="text/template" id="folder-tmpl">
        <li>
            <a href="#" class="folder"><%= folder.title %></a>
            <% if(folder.children.length) { %><ul><% } %>
            <% _.each(folder.children, function(child) { %>
                <%= templateFn({"folder": child, "templateFn": templateFn}) %>
            <% }); %>
            <% if(folder.children.length) { %></ul><% } %>
        </li>
    </script>
    

    【讨论】:

    • 是否可以将此方法与视图模型之类的东西一起使用。像数据处理应该在视图模型中完成,然后将其传递给模板进行每次递归
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    • 2011-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多