【问题标题】:How to render array into specific form for mustache to render如何将数组渲染为特定形式以供小胡子渲染
【发布时间】:2026-01-26 11:25:01
【问题描述】:

我通过 API 获得了一组带有图像位置的对象,但我无法渲染它。

我设法使用下划线将我的数组分成 4 个块,但我不知道如何将我的数据按摩成正确的形式,因此我可以通过小胡子将其渲染出来。

目前的代码如下所示:

var template = "<ul>{{#images}}<li>{{location}}</li>{{/images}}</ul>";

var data = [
    {"location":"gallery\/Baar_Toit_5.jpg"},
    {"location":"gallery\/Baar_Toit_7.jpg"},
    {"location":"gallery\/Baar_Toit_8.jpg"},
    {"location":"gallery\/Baar_Int_1.jpg"},
    {"location":"gallery\/Baar_Int_2.jpg"},
    {"location":"gallery\/Baar_Int_3.jpg"},
    {"location":"gallery\/Baar_Int_4.jpg"},
    {"location":"gallery\/Baar_Uus_01.jpg"},
    {"location":"gallery\/Baar_Uus_02.jpg"},
    {"location":"gallery\/Baar_Uus_03.jpg"},
    {"location":"gallery\/Baar_Uus_04.jpg"},
    {"location":"gallery\/Baar_Uus_05.jpg"},
    {"location":"gallery\/Baar_Uus_06.jpg"},
    {"location":"gallery\/Baar_Uus_07.jpg"}
];

var n = 4;
var imgs = _.groupBy(data, function(element, index){
    return Math.floor(index/n);
});

console.log(imgs);

Mustache.parse(template);
var rendered = Mustache.render(template, { imgs: JSON.parse(imgs) });
$('#gallery').html(rendered);

我创建了一个小沙盒用于测试目的,请随意使用它:http://jsfiddle.net/qK5NT/149/

我想要的输出是:

<ul>
    <li>
        <p>img/1.jpg</p>
        <p>img/2.jpg</p>
        <p>img/3.jpg</p>
        <p>img/4.jpg</p>
    </li>
    <li>
        <p>img/5.jpg</p>
        <p>img/6.jpg</p>
        <p>img/5.jpg</p>
        <p>img/6.jpg</p>
    </li>
    <li>
        <p>img/5.jpg</p>
        <p>img/6.jpg</p>
        <p>img/5.jpg</p>
        <p>img/6.jpg</p>
    </li>
    <li>
        <p>img/5.jpg</p>
        <p>img/6.jpg</p>
    </li>
</ul>

任何帮助将不胜感激!

【问题讨论】:

    标签: javascript html underscore.js mustache


    【解决方案1】:

    groupBy 不是这项工作的正确工具,对象在 JavaScript 中没有排序,因此无法保证您会以正确的顺序获得块。是的,这意味着分块的canonical answer 是错误的。

    所以你的第一个问题是正确地分块数据。如果你使用 lodash,你可以使用它的_.chunk。如果你使用的是普通的下划线,你可以混入你自己的_.chunk 并且可以很容易地适应 lodash 版本:

    _.mixin({
        chunk: function(a, n) {
            // Based on lodash's
            var i = 0, length = a.length, ri = -1;
            var result = Array(Math.ceil(length / n));
            while(i < length)
                result[++ri] = a.slice(i, i += n);
            return result;
        }
    });
    

    现在您可以将数据分成四份,并按照正确的顺序得到一个数组数组:

    var chunks = _(data).chunk(4);
    

    然后你想把chunks交给你的模板:

    var rendered = Mustache.render(template, {
        chunks: chunks
    });
    

    最后,您的模板需要遍历块以生成&lt;li&gt;s,然后遍历每个块以在&lt;li&gt;s 中生成&lt;p&gt;s。看起来像这样:

    <ul>
        {{#chunks}}
            <li>
                {{#.}}
                    <p>{{location}}</p>
                {{/.}}
            </li>
        {{/chunks}}
    </ul>
    

    演示:http://jsfiddle.net/ambiguous/b2te16pj/

    【讨论】:

    • 除了示例在返回的对象上调用.toArray,所以你会得到一个有序数组。
    • @ColinDeClue:但_.toArray(some_object) 不保证它会按其键对some_object 进行排序,toArray 只会遍历对象并以任何顺序为您提供值@987654340 @ 将使用(即根本没有指定的顺序)。在groupBy 上添加toArray 调用并不能解决订单问题。
    • @mu 太短:谢谢你这么棒的回答!
    • @muistooshort:啊,我以为它会关闭对象中的键。但是,是的,只有当键始终是数字时才会起作用,这是无法保证的。
    • @ColinDeClue:键是 always 字符串,但键是什么并不重要,因为没有任何地方可以对它们进行排序。对象的键没有排序,toArray 在内部使用_.values_.keys(至少当前版本是这样)并且它们都没有对键进行排序(如果这样做它们会出错,因为键是字符串和'2''11' 不要像数字一样排序)。其他实现依赖于意外和未指定的行为,所以它是错误的。