Рекурсия Mustache.js
Я пытаюсь построить html-дерево с помощью Mustache.js, но это не позволяет выполнить "Максимальный размер стека вызовов", возможно, из-за бесконечной рекурсии.
Что не так?
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);
Ответы
Ответ 1
Проблема присуща реализации в Mustache.js(отказ от ответственности: не уверен, что проблема в самой спецификации), поскольку алгоритм ищет свойство в своем родителе, когда он не может найти его в текущем контексте.
Чтобы объяснить это кратко: код запускается на вашем шаблоне, выводит Gar1<ul>
и находит тег {{#children}}
. Так как ваш контекст имеет дочерний тег, он выдает <li>
и вызывает частичное, которое теперь будет выполняться во внутреннем контексте {title: 'gar2'}
. Когда Mustache снова достигнет вашего тега {{#children}}
, теперь выясняется, что текущий контекст не имеет свойства children
, поэтому он идет на один уровень вверх, где он действительно находит ваше дочернее свойство и начинает рекурсировать (это настоящее слово?) Снова на себе, как сумасшедший.
Два возможных решения:
1 - измените свои данные, чтобы все записи имели свойство children
, а когда node не должно быть детей, установите его на false
или null
(а не на пустой массив) следующим образом:
var root = {
title: 'Gar1',
children: [{title: 'gar2', children: false}, {title: 'gar3', children: [{title: 'gar4', children: false}]}]
};
2 - используйте Handlebars вместо Mustache и оберните <ul>
тегом {{#if children}}
.
Надеюсь, это поможет, я знаю, что ответ немного запоздал, так как это было задано.
Ответ 2
Вот один объект, который нуждается в рекурсии.
Объект
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'
}
});
Вывод этого примера
Btw Я использую Hogan.js для рендеринга шаблона. Я не знаю, поддерживает ли Mustache.js рекурсию или нет.