在ng-repeat中的某些元素周围添加包装器

时间:2015-04-30 15:27:08

标签: javascript css angularjs

可以使用ng-repeat来实现以下编译的DOM:

<div class="container">
    <!-- ngRepeat item in items -->
    <div ng-repeat="item in items">Item 1</div>
    <!-- end ngRepeat: item in items -->
    <!-- ngRepeat item in items -->
    <div ng-repeat="item in items">Item 2</div>
    <!-- end ngRepeat: item in items -->
    <!-- ngRepeat item in items -->
    <div ng-repeat="item in items">Item 3</div>
    <!-- end ngRepeat: item in items -->
    <div class="wrapper">
        <!-- ngRepeat item in items -->
        <div ng-repeat="item in items">Item 4</div>
        <!-- end ngRepeat: item in items -->
        <div ng-repeat="item in items">Item 5</div>
        <!-- end ngRepeat: item in items -->
   </div>
</div>

即。将最后n个项目包含在另一个元素中。

这似乎是一个奇怪的请求,我理解使用两个ng-repeat指令实现这一点是微不足道的。但是,它需要是单个ng-repeat,以便我可以将项目移入和移出包装器,而无需将它们添加到DOM中(以here描述的方式)。

我尝试实现的是通过提供.wrapper元素overflow:hidden并使用javascript为子元素的top位置设置动画来实现新闻 - 滚动效果滚动效果。说实话,我根本不需要包装元素,但我不确定是否有任何其他方法可以实现我需要的滚动效果。也许操纵clip属性来实现效果可能有效,但我并不完全确定。

因此可以将包装元素应用于ng-repeat

中的某些项目

3 个答案:

答案 0 :(得分:2)

不幸的是,当您更改可视树中元素的父元素时,必须将其删除并重新添加。在其他问题中,请考虑样式规则如何根据谁是其父母而应用不同的规则。在动画制作中,这也是一件相当昂贵的事情。

令人失望?也许

但通过阅读您的用例,我认为您会发现Angular非常擅长使用一小段代码来处理这类动画。我已经为你提供了一个小提琴:

http://jsfiddle.net/wjxgcb0k/

创建自己的布局并将其绑定到页面上的元素非常容易。我们首先使用ng-repeat为每个项目吐出一行:

<div class="container" ng-app ng-controller="Foo">
    <div class="item"
        ng-repeat="item in items" 
        ng-style="{'top': item.top + 'px'}">{{item.name}}
    </div>
</div>

因为我们想要处理我们自己的布局,所以容器中的每个项目都是position: absolute。了解我们如何将top绑定到item.top + 'px'?我们需要做的就是在动画循环中调整那些最高值。我将使用requestAnimationFrame,因为它是我手动动画的工具,但如果你更舒服,可以使用css过渡或动画。

我将初始化控制器中的顶部值。这就是它的含义,持有状态:

$scope.items.forEach(function(item, idx) {
    item.h = height;
    item.top = idx * (height + margin);
    console.log(item);
});

然后我会建立一个动画循环:

var tick = function() {
    $scope.$apply(function() {
        $scope.items.forEach(function(item, idx) {
            item.top -= velocity;
            if (item.top < -(height + margin)) {
                item.top += $scope.items.length * (height + margin);
            }
        });
    });
    requestAnimationFrame(tick);
};

然后开始整个事情:

requestAnimationFrame(tick);    

您可以通过以下方式进行一些改进:

  • 仅考虑设置适合页面的项目,而不是集合中的所有项目。表演会感谢你。
  • 不依靠$apply将更改传播到Dom,而是直接自行操作样式。这可以提高动画性能。
  • if条件触发并且我们将项目重置到自动收报机底部时,我们可能会检查是否有不同的内容要放入自动收报机项目中。这样,您可能会有一个随时间变化的实时更新代码。
  • 尝试将所有工作水平放置。或者可能调整不透明度,因为顶部接近零或列表的下半部分。

我希望这会有所帮助,我希望执行此操作所需的少量代码会鼓励您抛弃依赖HTML为您进行布局的概念。

答案 1 :(得分:0)

我实际上不知道是否可以使用ng-repeat在块内包装N个项目。但是可以做的是将.wrapper类应用于索引高于'some value'的每个元素。这可以使用ng-class和$ index完成。

编辑: 希望我明白新股票的运作方式。如果没有,抱歉答错了。

plnkr

<div ng-repeat="op in options" ng-class="{wrapper: $index > limit}">{{op.title}}</div>

在示例中,您可以更改'limit'变量的模型值以更改可见项的数量。

或更好。如果包装内的项目应该“出现”,那么最简单的方法就是

ng-hide="$index > end || $index < start"

这会在开头和结尾隐藏项目。操纵'start'和'end'的值会产生效果。

答案 2 :(得分:0)

从技术上讲,答案是否定的,因为wrapper存在于ngRepeat范围之外。因此,根据每个wrapper的属性,无法在item上设置条件。

另一方面,您仍然可以重现相同的标记。它只需要过滤和一些创造性思维。

 <div class="container">
      <!-- items with wrapper = false are outside wrapper -->
      <div ng-repeat="item in items | {'wrapper':false}">{{item}}</div>
      <div class="wrapper">
          <!-- items with wrapper = true are inside wrapper -->
          <div ng-repeat="item in items | {'wrapper':true}">{{item}}</div>
      </div>
 </div>