91

我目前正在使用这段代码来呈现一个列表:

<ul ng-cloak>
    <div ng-repeat="n in list">
        <li><a href="{{ n[1] }}">{{ n[0] }}</a></li>
        <li class="divider"></i>
    </div>
    <li>Additional item</li> 
</ul>

但是,该<div>元素在某些浏览器上会导致一些非常小的渲染缺陷。我想知道有没有办法在没有 div 容器的情况下执行 ng-repeat,或者有一些替​​代方法可以达到相同的效果。

4

7 回答 7

104

正如 Andy Joslin 所说,他们正在研究基于评论的 ng-repeats ,但显然存在太多浏览器问题。幸运的是,AngularJS 1.2 添加了对重复的内置支持,而无需使用新指令添加子元素ng-repeat-startng-repeat-end.

下面是一个添加Bootstrap 分页的小例子:

<ul class="pagination">
  <li>
    <a href="#">&laquo;</a>
  </li>
  <li ng-repeat-start="page in [1,2,3,4,5,6]"><a href="#">{{page}}</a></li>
  <li ng-repeat-end class="divider"></li>
  <li>
    <a href="#">&raquo;</a>
  </li>
</ul>

可以在此处找到完整的工作示例。

John Lindquist在他出色的 egghead.io 页面上也有一个视频教程

于 2013-09-16T09:08:00.897 回答
30

KnockoutJS 无容器绑定语法

请耐心等待:KnockoutJS 提供了一个非常方便的选项,即使用无容器绑定语法进行绑定,如绑定文档 foreach的注释 4 中所述。http://knockoutjs.com/documentation/foreach-binding.htmlforeach

正如 Knockout 文档示例所示,您可以像这样在 KnockoutJS 中编写绑定:

<ul>
    <li class="header">Header item</li>
    <!-- ko foreach: myItems -->
        <li>Item <span data-bind="text: $data"></span></li>
    <!-- /ko -->
</ul>

我认为 AngularJS 不提供这种类型的语法是相当不幸的。


角的ng-repeat-startng-repeat-end

在 AngularJS 解决ng-repeat问题的方法中,我遇到的示例属于 jmagnusson 在他的(有用的)答案中发布的类型。

<li ng-repeat-start="page in [1,2,3,4,5]"><a href="#">{{page}}</a></li>
<li ng-repeat-end></li>

看到这种语法,我最初的想法是:真的吗?为什么 Angular 会强制所有这些我不想做的额外标记,而这在 Knockout 中要容易得多?但后来 jmagnusson 回答中的 hitautodestruct 评论开始让我想知道:在单独的标签上使用 ng-repeat-start 和 ng-repeat-end 生成了什么?


更清洁的使用方式ng-repeat-startng-repeat-end

在对 hitautodestruct 的断言进行调查后,在大多数情况下,添加ng-repeat-end到单独的标签正是我不想做的,因为它会生成完全无用的元素:在这种情况下,<li>项目中什么都没有。Bootstrap 3 的分页列表设置了列表项的样式,因此看起来您没有生成任何多余的项,但是当您检查生成的 html 时,它们就在那里。

幸运的是,您不需要做太多事情来获得更简洁的解决方案和更短的 html:只需将ng-repeat-end声明放在具有ng-repeat-start.

<ul class="pagination">
  <li>
    <a href="#">&laquo;</a>
  </li>    
  <li ng-repeat-start="page in [1,2,3,4,5]" ng-repeat-end><a href="#"></a></li>
  <li>
    <a href="#">&raquo;</a>
  </li>
</ul>

这有 3 个优点:

  1. 少写html标签
  2. Angular 不会生成无用的空标签
  3. 当要重复的数组为空时,ng-repeat不会生成带有的标签,这与 Knockout 的无容器绑定在这方面为您提供的优势相同

但是还有一种更清洁的方法

在进一步查看 github 中关于 Angular 的这个问题的评论后,https://github.com/angular/angular.js/issues/1891
您不需要使用ng-repeat-startng-repeat-end获得相同的优势。相反,再次分叉 jmagnusson 的例子,我们可以去:

<ul class="pagination">
  <li>
    <a href="#">&laquo;</a>
  </li>
  <li ng-repeat="page in [1,2,3,4,5,6]"><a href="#">{{page}}</a></li>
  <li>
    <a href="#">&raquo;</a>
  </li>
</ul>

那么什么时候使用ng-repeat-startandng-repeat-end呢?根据角度文档,到

...重复一系列元素,而不仅仅是一个父元素...

废话不多说,举几个例子吧!

很公平; 这个 jsbin 将通过五个示例来说明当你ng-repeat-end在同一个标​​签上使用和不使用时会发生什么。

http://jsbin.com/eXaPibI/1/

于 2014-01-30T01:16:50.433 回答
6

ngRepeat 可能还不够,但是您可以将其与自定义指令结合使用。如果您不介意一点 jQuery,您可以将添加分隔项的任务委托给代码。

 <li ng-repeat="item in coll" so-add-divide="your exp here"></li>

这样一个简单的指令实际上并不需要属性值,但可能会给你很多可能性,比如根据索引、长度等有条件地添加分隔符或完全不同的东西。

于 2012-10-12T20:58:46.723 回答
3

我最近遇到了同样的问题,因为我不得不重复任意的跨度和图像集合——在它们周围有一个元素不是一种选择——但是有一个简单的解决方案,创建一个“null”指令:

app.directive("diNull", function() {
        return {
            restrict: "E",
            replace: true,
            template: ""
        };
    });

然后,您可以在该元素上使用重复,其中 element.url 指向该元素的模板:

<di-null ng-repeat="element in elements" ng-include="element.url" ></di-null>

这将重复任意数量的不同模板,它们周围没有容器

注意:嗯,我可以发誓这在渲染时删除了 di-null 元素,但再次检查它并没有......仍然解决了我的布局问题......curioser和curioser......

于 2013-09-17T11:54:23.227 回答
2

真正有效的解决方案

html

<remove  ng-repeat-start="itemGroup in Groups" ></remove>
   html stuff in here including inner repeating loops if you want
<remove  ng-repeat-end></remove>

添加一个 angular.js 指令

//remove directive
(function(){
    var remove = function(){

        return {    
            restrict: "E",
            replace: true,
            link: function(scope, element, attrs, controller){
                element.replaceWith('<!--removed element-->');
            }
        };

    };
    var module = angular.module("app" );
    module.directive('remove', [remove]);
}());

简要说明,

ng-repeat 将自身绑定到<remove>元素并循环,因为我们使用了 ng-repeat-start / ng-repeat-end 它循环一个 html 块而不仅仅是一个元素。

然后自定义删除指令将<remove>开始和结束元素放置在<!--removed element-->

于 2019-07-20T22:40:21.697 回答
1

有一个注释指令限制,但 ngRepeat 不支持它(因为它需要一个元素来重复)。

我想我看到 Angular 团队说他们会处理评论 ng-repeats,但我不确定。您应该在 repo 上为它打开一个问题。 http://github.com/angular/angular.js

于 2012-10-12T12:04:00.873 回答
1

如果您使用的是 Bootstrap,则没有 Angular 魔术方法可以做到这一点,对于您的情况,您可以这样做以获得有效的 HTML。然后你会得到与添加 li.divider 相同的效果

创建一个类:

span.divider {
 display: block;
}

现在将您的代码更改为:

<ul ng-cloak>
 <li div ng-repeat="n in list">
    <a href="{{ n[1] }}">{{ n[0] }}</a>
    <span class="divider"></span>
 </li>
 <li>Additional item</li>
</ul>
于 2015-05-13T11:49:18.243 回答