【问题标题】:Write custom iterator for Spacebars为空格键编写自定义迭代器
【发布时间】:2015-06-29 07:33:21
【问题描述】:

我正在尝试在空格键中编写自定义迭代器(我使用的是流星 1.1.3)。迭代器将是一个顺序 for 循环(基本上是在需要时替换我对 #each 的使用,因为我相信 #each 不能保证在其迭代中是顺序的)。

我尝试了以下方法:

在库中 -

UI.registerHelper 'sequentialFor', () ->
  ret = ""
  for i in [0...@.length]
    id = @[i]
    ret = ret + Template.noop
  ret

noop.html -

<template name="noop">
  {{> UI.contentBlock this}}
<template>

main.html -

{{#sequentialFor ids}}
<div id="wow-{{this}}">stuff</div>
{{/sequentialFor}}

上面的 ids 是一个从 main 的模板助手传递过来的字符串数组。

现在它抱怨我的 UI 助手返回的是 [object Object] [object Object]。 为了理智,我知道如果我将 UI 助手替换为:

UI.registerHelper 'sequentialFor', () ->
  //ret = ""
  //for i in [0...@.length]
    //  id = @[i]
    //  ret = ret + template
  id = @[0]
  Template.noop

我知道 main.html 中的 div 会根据需要显示适当的 id 作为其 id 属性的一部分。但是,我似乎无法使 for 循环工作。

我不能简单地直接从帮助程序返回 main.html 中的 div,因为我需要用我的新迭代器包装很多 div,每个 div 都有非常不同的属性。

我想一个简单的问题是,如何在空格键中定义我自己的块迭代器(类似于#each)?

更困难的问题可能是,我上面的方法有什么问题?

我考虑了很多资源,但只发现以下内容非常有用: How to pass an object from to a block helper back to the block in meteor blaze? https://github.com/meteor/meteor/wiki/Using-Blaze https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md Iterating over basic “for” loop using Handlebars.js

注意我正在使用咖啡脚本

【问题讨论】:

  • 如果您在 mongo 查询中使用排序,则每个都没有排序?
  • for 循环不起作用,因为this 不是数组。
  • {{#each}} 在一个数组上将被排序。
  • @user3374348 据我所知,我不相信 {{#each}} 保证是连续的。请参阅下面我对 pfkurtz 回答的评论,以更好地了解我的担忧。

标签: meteor coffeescript meteor-blaze spacebars


【解决方案1】:

我设法使用类似于您在 Haskell 或 Lisp 中使用的递归技术获得了自定义迭代器:

<body>
  {{#countdown n=5}}
    <p>item {{this}}</p>
  {{/countdown}}
</body>

<template name="countdown">
  {{#if positive}}
    {{> Template.contentBlock n}}
    {{#countdown n=nMinusOne}}
      {{> Template.contentBlock this}}
    {{/countdown}}
  {{/if}}
</template>
Template.countdown.helpers({
  positive: function () {return this.n > 0;},
  nMinusOne: function () {return this.n - 1;}
});

meteorpad

性能可能比平时的{{#each}}差很多。

【讨论】:

  • 感谢您的详细回答。我认为这是迄今为止最好的一个。但是,我不会将其标记为解决方案,直到我确定没有编写自定义迭代器的标准方法(就像以前那样)。无论哪种方式都支持投票。
【解决方案2】:

在我看来,您想为每个 ID 数组创建一个 &lt;div&gt;(如果我错了,请纠正我)。我就是这样做的,不需要自定义迭代器:

Template.registerHelper('ids', function(arrayWithIds) {
    if (!arrayWithIds) return [];
    // do some sorting or whatever with arrayWithIds, for example:
    var arrayOfIds = _.map(arrayWithIds, function(obj) {
        return obj._id;
    });
    return arrayOfIds;
});

然后在main.html中:

{{#each ids someDataSetWithIds}}
    // `someDataSetWithIds` is the helper's parameter
    // `this` in each case is an ID
    <div id="wow-{{this}}"></div>
{{/each}}

如果你的助手返回一个对象,你可以在模板中使用this._id。我误解了你想要达到的目标吗?

【讨论】:

  • 我很欣赏这个答案,但这并不能解决我的问题。正如您在回答中所做的那样,我已经可以创建这些 div(每个 id 一个)。我要解决的问题是(据我所知)空格键并不能保证 #each 始终是同步的(即使使用它当前的实现也是如此)。保证顺序迭代对我的应用程序非常重要,因此我正在尝试编写一个顺序迭代器来代替空格键中的标准 #each 迭代器。
  • 即使我创建这个迭代器的原因似乎是偏执的,请随时从一般如何创建/重新创建空格键迭代器 {{#each}} 的角度来解决我的问题