问题描述

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

<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,或者一些替代方法来达到同样的效果。

最佳解决方案

正如 Andy Joslin 所说,他们正在从事基于评论的 ng-repeats but apparently there were too many browser issues 。幸运的是 AngularJS 1.2 添加了内置支持重复,而不用新的指令 ng-repeat-startng-repeat-end 添加子元素。

以下是添加 Bootstrap pagination 的一个例子:

<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>

一个完整的工作实例可以找到 here

约翰·林德奎斯特也有一个 video tutorial of this over at his excellent egghead.io page

次佳解决方案

KnockoutJS 无容器绑定语法

请耐心等待一次:KnockoutJS 提供了一个 ultra-convenient 选项,该选项对 foreach 绑定使用无容器绑定语法,如 foreach 绑定文档的注 4 所述。 http://knockoutjs.com/documentation/foreach-binding.html

如 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 相同的 html 标签上即可。

<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>

这有三个优点:

  1. 较少的 html 标签要写

  2. 没有用的空标签不是由 Angular 生成的

  3. 当要重复的数组为空时,ng-repeat 的标签将不会生成,给予您同样的优势 Knockout 的无容器绑定在这方面给你


但仍然有一个更清洁的方法

在对 Angular,https://github.com/angular/angular.js/issues/1891 这个问题进一步审查 github 的意见后,您不需要使用 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-startng-repeat-end?根据 angular documentation,至

…repeat a series of elements instead of just one parent element…

足够讲话,展示一些例子!

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

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

第三种解决方案

ngRepeat 可能还不够,但是您可以将其与自定义指令组合。如果你不介意一点点的 jQuery,你可以委托把代码添加到代码中的任务。

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

这样一个简单的指令并不需要一个属性值,但是可能会给你很多可能性,例如有条件地根据索引,长度等添加一个除法器,或者完全不同。

第四种方案

我最近有同样的问题,因为我不得不重复任意的跨度和图像的集合 – 在它们周围有一个元素不是一个选择 – 但是有一个简单的解决方案,创建一个”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 …

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛