Mustache.js递归

时间:2012-11-16 00:06:46

标签: javascript node.js mustache

我正在尝试使用Mustache.js构建一个html树,但它无法抛出“超出最大调用堆栈大小”,可能是因为无限递归。

怎么了?

var Mustache = require('mustache');

var root = {
    title: 'Gar1',
    children: [{title: 'gar2'}, {title: 'gar3', children: [{title: 'gar4'}]}]
};

var panelTemplate = '{{title}}<ul>{{#children}}<li>{{>panel}}</li>{{/children}}</ul>';

var partials = {panel: panelTemplate};
var output = Mustache.render(panelTemplate, root, partials);


console.log(output);

2 个答案:

答案 0 :(得分:18)

问题是Mustache.js中的实现所固有的(免责声明:不确定问题是否在规范本身中),因为当算法在上找不到属性时在当前背景下找到它。

简要解释一下:代码在您的模板上运行,输出Gar1<ul>并找到{{#children}}标记。由于您的上下文有一个子标记,它会输出<li>并调用现在将在内部上下文{title: 'gar2'}上运行的部分。当Mustache再次到达你的{{#children}}标签时,它现在发现当前上下文没有children属性,因此它在实际找到你的children属性并开始递归的位置上升一级(这是真的这个词?)就像疯了一样。

两种可能的解决方案:

1 - 修改您的数据,以便所有条目都具有children属性,当节点没有子节点时,将其设置为falsenull (不是空数组)像这样:

var root = {
    title: 'Gar1',
    children: [{title: 'gar2', children: false}, {title: 'gar3', children: [{title: 'gar4', children: false}]}]
};

2 - 使用Handlebars而不是Mustache,并将<ul>包裹在{{#if children}}标记中。

希望这有帮助,我知道答案有点晚了,因为有人问过。

答案 1 :(得分:5)

这是一个需要递归的对象。

对象

var obj = [
    {
        obj: true,
        key: 'a',
        value: [
            {
                obj: false,
                key: 'a',
                value: 1
            },
            {
                obj: false,
                key: 'b',
                value: 2
            },
            {
                obj: true,
                key: 'c',
                value: [
                    {
                        obj: false,
                        key: 'a',
                        value: 3
                    }
                ]
            }
        ]
    },
    {
        obj: false,
        key: 'b',
        value: 4
    }
];

模板(recursion.html)。

<!-- root -->
<ul>
    {{#value}}
    <li>
        <!-- object -->
        {{#obj}}
        <span><b>{{key}}</b></span>
        {{>object}}
        {{/obj}}
        <!-- value -->
        {{^obj}}
        <span><b>{{key}}</b> <span>{{value}}</span></span>
        {{/obj}}
    </li>
    {{/value}}
</ul>

您传入的第一个对象是没有key的根只有value。如果value将属性obj设置为true,那么它就是一个对象,打印出其密钥并再次递归调用模板以获取其值。 如果不是对象则不需要递归,只需打印出来。

渲染客户端。

// html is recursion.html contents
var template = Hogan.compile(html),
    content = template.render({value: obj}, {object: html});
// show the rendered template
$('body').empty().append(content);

使用Express.js

渲染服务器端
res.render('recursion', {
    value: obj,
    partials: {
        object: 'recursion'
    }
});

此示例的输出

http://jsfiddle.net/simo/GYjMY/

顺便说一句,我正在使用Hogan.js渲染模板。我不知道Mustache.js渲染是否支持递归。