除了最后一个元素之后,如何在 #each 循环中的元素之间添加分隔符?

Posted

技术标签:

【中文标题】除了最后一个元素之后,如何在 #each 循环中的元素之间添加分隔符?【英文标题】:How do I add a separator between elements in an #each loop except after the last element?除了最后一个元素之后,如何在 #each 循环中的元素之间添加分隔符? 【发布时间】:2012-05-11 07:02:03 【问题描述】:

我有一个 Handlebars 模板,我正在尝试从数组中生成以逗号分隔的项目列表。

在我的 Handlebars 模板中:

#each list
    name status,
/each

我希望, 不显示在最后一项上。有没有办法在 Handlebars 中做到这一点,还是我需要回退到 CSS 选择器?

更新:根据 Christopher 的建议,这是我最终实施的:

var attachments = Ember.CollectionView.extend(
    content: [],
    itemViewClass: Ember.View.extend(
        templateName: 'attachments',
        tagName: 'span',
        isLastItem: function() 
            return this.getPath('parentView.content.lastObject') == this.get('content');
        .property('parentView.content.lastObject').cacheable()
    )
));

在我看来:

collection attachments

和项目视图:

content.title (content.size) #unless isLastItem, /unless

【问题讨论】:

我发现的另一件事是,如果您删除最后一个项目,则需要强制重绘每个项目以删除最后一个分隔符。默认情况下,删除一个项目似乎只会删除该项目的视图,而其他项目不会更新(这是有道理的)。 【参考方案1】:

您可以使用标准 CSS 来执行此操作:

li:after 
    content: ',';


li:last-of-type:after 
    content: '';

我更喜欢单独的规则,但更简洁但可读性稍差的版本(来自 cmets 中的 @Jay):

li:not(:last-of-type):after 
    content: ',';

【讨论】:

我研究了 last-child ,虽然它会很好用,除了它在 IE8 中不受支持。我会给计算的属性一个镜头。没有内置的方式来制作分隔列表,这对我来说仍然很奇怪。 您可以使用li + li:before,而不是使用:afterlast-child,这使得它能够可靠地抵御IE8(不要忘记put it in standards compliant rendering mode!) 这太完美了!我将它与 Mustache.js 模板一起使用,但直到我开始四处寻找替代品(我现在不需要它!)时才找到它。 我已经编辑了下面的答案,也许您也应该将这种新语法合并到您的答案中。 我进行了编辑以删除旧的笨拙的后备。如果你还在关心 IE8……上帝怜悯你的灵魂。我仍然更喜欢明确的单独规则,但每个人都有自己的规则。【参考方案2】:

使用 ember 2.7,您可以在安装 ember-truth-helpers 后执行此操作:

ember install ember-truth-helpers

然后您的模板将如下所示:

#each model as |e|
    e#unless (eq e model.lastObject), /unless
/each

【讨论】:

【参考方案3】:

从 Ember v1.11 开始,您可以使用块参数获取每个索引的索引。在你的情况下,这看起来像这样:

#each list as |item index|
    if index ", "item.name item.status
/each

第一个index 值将是0,它将评估为false 并且不会被添加,所有后续值将评估为true,它将在前面添加一个分隔符。

【讨论】:

这不符合问题。你仍然在最后一个元素中得到一个逗号...... @MarcusRenno 因此它位于元素内容之前。 是的,我不知道我在想什么。现在我再次阅读代码完全有意义【参考方案4】:

我知道我迟到了,但我找到了一个 WAYYYY 更简单的方法

#unless @last,/unless

【讨论】:

如果您使用 Ember 的车把,这不是。 我没有使用 Ember,但我在寻找一种方法时遇到了这个线程,它运行良好。谢谢! 类似的注释:#if @index,/if ***.com/a/20575093/923745 -- 应该与 Ember 一起使用。 如果您想知道的话,可以在 jsreport 车把引擎中完美运行【参考方案5】:

我已经创建了 sep 块助手:

Handlebars.registerHelper("sep", function(options)
    if(options.data.last) 
        return options.inverse();
     else 
        return options.fn();
    
);

用法:

#each Data
   Text#sep,/sep
/each

支持 else 语句。

【讨论】:

【参考方案6】:

我得到了这个修改版本的freak3dot的答案:

handlebars.registerHelper('csv', function(items, options) 
  return items.map(function(item) 
    return options.fn(item)
  ).join(', ')
)

(这是一个节点应用程序,因此如果您在浏览器中构建,请将map 相应地更改为下划线或其他内容)

允许在每个逗号之间格式化对象:

#csv players
  firstName lastName
/csv

编辑:这是一个更灵活的版本。在任意分隔符上加入事物列表。

handlebars.registerHelper('join', function(items, separator, options) 
  return items.map(function(item) 
    return options.fn(item)
  ).join(separator)
)

和模板:

#join players ' vs '
  firstName lastName
/join

【讨论】:

【参考方案7】:

我意识到这已经一岁了,但我遇到了类似的问题并在这里结束了。就我而言,我实际上是在处理一个数组。所以,这是我的解决方案。

Handlebars.registerHelper('csv', function(items, options) 
    return options.fn(items.join(', '));
);

// then your template would be
#csv listthis/csv

我想要一个简单而优雅的解决方案,将 csv 逻辑保留在模板中。

【讨论】:

【参考方案8】:

也许在这种情况下,您应该为集合创建一个视图,而不是成员项上的视图迭代。在这种情况下,Handlebar 迭代器是多余的。在下面的示例中,对 Person 对象的 firstName 或 lastName 的更改将绑定到列表并更新视图。

模板:

App.listController.csv

javascript

App = Ember.Application.create();

var Person = Ember.Object.extend(
    firstName: null,
    lastName: null
);

var bob = Person.create(
    firstName: "bob",
    lastName: "smith"
);

var ann = Person.create(
    firstName: "ann",
    lastName: "doe"
);

App.listController = Ember.Object.create(
    list: [bob, ann],
    csv: Ember.computed(function () 
        var arr = [];
        this.get('list').forEach(function (item, index, self) 
            arr.push(item.firstName + ' ' + item.lastName);
        )
        return arr.join(',');
        ).property('list.@each.firstName', 'list.@each.lastName')
);
// any changes to bob or ann will update the view
bob.set('firstName', 'tim');
// adding or removing from the array will update the view
App.listController.get('list').pushObject(Person.create(firstName: "Jack", lastName:"Dunn");

以下是我的原始答案,不适用于这种情况。

你应该可以通过助手来做到这一点:

Handlebars.registerHelper('csv', function(items, options) 
  var out = "";
  for(var i=0, l=items.length; i<l; i++) 
    out += options.fn(items[i]);
    if (i < l - 1) 
        out += ',';
    
    // might want to add a newline char or something
   
  return out;
);

// then your template would be
#csv list name status /each

【讨论】:

不幸的是,这不适用于 Ember.js 中的数据绑定。 我最终做了类似的事情,但使用了 Ember.js ContainerView,它支持每个项目的 Handlebars 模板,然后是一个计算属性,说明当前项目是否是父列表中的最后一个项目或不。请参阅我的更新答案。如果您不需要使用花哨的 html 模板(就像我正在做的那样),这看起来是一个不错的选择。

以上是关于除了最后一个元素之后,如何在 #each 循环中的元素之间添加分隔符?的主要内容,如果未能解决你的问题,请参考以下文章

你如何找到 For Each (VB.NET) 中的最后一个循环?

如何在 $.each 中的 jquery prependTo 之前和之后添加静态 HTML

PHP——数组中的each(),list()和while循环遍历数组

浅谈for each循环

浅谈for each循环

如何在已排序的 xsl:for-each 循环中访问前一个和下一个元素的值