Mustache模板:嵌套模板

18

如何在mustache中使用嵌套模板?有没有相应的方法可以实现?

var tmpl="{{#data}} 
{{values}}
Name: {{name}}
//{{another_templ({{name.value}})}}
{{/values}}
{{/data}}"
希望大家已经明白了问题。由于代码分散在不同的行中,我没有添加JS有效性的转义字符。

2
为什么不使用partials?https://mustache.github.io/mustache.5.html#Partials - Pere
3个回答

8
您可以使用lambda来嵌套模板:
function nested_template(template_string, translate) {
  return function() {
    return function(text, render) {
      return Mustache.to_html(template_string, translate(render(text)));
    };
  };
}

var template_string = 
  "{{#data}}"+
    "{{values}}"+
      "Name: {{name}}"+
      "{{#another_templ}}{{name}}{{/another_templ}}"+
    "{{/values}}"+
  "{{/data}}";

var another_template_string = "<b>{{name}}</b>"; // for example

var view = {
  data: {
    values: {
      name: "Test"
    }
  },
  another_templ: nested_template(another_template_string, function(text) {
    return {name: text};
  });
};

var result = Mustache.to_html(template_string, view);

@Harry:不,唯一的方法是使用lambda,因为partials无法获取参数(除非你通过黑客方式解决:http://stackoverflow.com/questions/6656093/mustache-partials-using-variable-syntax-without-the)。 - marc
抱歉打扰了,但是你基本上是在重新实现Mustache中的一个现有功能。你应该使用partials;我从第一天开始就一直在使用它,它会像任何其他“正常”的标准模板一样呈现您的变量。你确定你正在正确使用partials吗,@marc? - Pere
感谢您的提问。在我看来,部分模板不能回答OP的问题,因为它们不允许传递参数,而是依赖于当前数据环境。请注意,此答案中的技术允许在/不同/上下文中重用其他模板,而部分模板只能在固定上下文中使用(因为它们期望特定的数据环境,而不是获取任意参数)。 - marc
首先,请注意我们似乎在谈论不同版本的Mustache。 "如何在mustache中使用嵌套模板?" 这是OP的问题。我认为“使用部分”可以回答这个问题。仍然不明白你的推理。在你的例子中,你的“任意参数”来自于你传递给lambda的“特定数据环境”。我想看看你的例子中有什么不能用简单的{{>partial}}来实现的。 - Pere
由于这是一个非常古老的问题,事情可能已经发生了改变 :) 如果OP不接受任何答案,很难说他想要什么。但我的印象是,他问如何将参数传递给模板,{{another_tpl({{name}})}}。所有答案都解释了如何做到这一点。想象一个通用的模板,例如用于使文本旁边有一个小图标以调用搜索功能。像这样的东西应该可用于任何文本,包括通过moustache自身生成的文本。如何使用partials解决这个问题? - marc
显示剩余2条评论

8
我已经在jsFiddle上制作了一个嵌套模板的示例。以下是详细步骤:
首先,设置你的HTML代码。
<div class="main"><!-- content here --></div>

<script type="text/html" id="tpl">
    {{#data}}
        {{#names}}
            Name: {{name}}
            {{#nested}}{{name}}{{/nested}}<br>
        {{/names}}
    {{/data}}
</script>

<script type="text/html" id="tpl-nested">
    &mdash; <b>{{name}}</b>
</script>

然后使用 JavaScript(使用 jQuery)。
function renderNested(template_string, translate) {
    return function() {
        return function(text, render) {
            return Mustache.to_html(template_string, translate(render(text)));
        };
    };
}

var template = $("#tpl").html();

var nested_template = $("#tpl-nested").html();

var model = {
    data: {
        names: [
            { name: "Foo" },
            { name: "Bar" }
        ],
        nested: renderNested(nested_template, function(text) {
            return { name: text };
        })
    }
};

var result = Mustache.to_html(template, model);

$(".main").html( result );

我走了类似的方向,只是在模板中放置了子模板的名称,例如{{#nested}}tpl-nested{{/nested}},请参见https://jsfiddle.net/omnius/env3d7wk/,但我遇到的问题是当嵌套多个级别时它不起作用,我不知道为什么会这样。我认为我已经理解了,因为我一直在使用相同的渲染器,所以它应该使用相同的数据模型,其中包括子模板加载器。你有任何想法为什么我的Fiddle不能做子子模板吗? - Scott Gartner

0

这里有一种方法,我们在编译模板之前进行字符串替换。 子模板通过以下方式在模板中调用: {{#template}}插入您的子模板名称{{/template}}

templates = {}

function compileTemplates(templateNamesArray) {
    for (index in templateNamesArray) {
        var templateName = templateNamesArray[index];
        var baseHTML = $('#' + templateName).html();

        var start = baseHTML.indexOf("{{#template}}");
        while(start != -1) {
            var end = baseHTML.indexOf('{{/template}}', start);
            var nestedTemplateName = baseHTML.slice(start + "{{#template}}".length, end);
            var nestedTemplateEl = $('#' + nestedTemplateName);
            if (nestedTemplateEl.length == 0) {
                throw "Could not find nested template '" + nestedTemplateName + "' for the template '" + templateName + "'";
            }
            baseHTML = baseHTML.slice(0, start) + nestedTemplateEl.html() + baseHTML.slice(end + '{{/template}}'.length);
            start = baseHTML.indexOf("{{#template}}", start);
        }
        templates[templateName] = Handlebars.compile(baseHTML);
    }
}

compileTemplates(["templateActiveThreadTab", "templateActiveThreadContent", "templateTodoItem"]);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接