2011-06-22 36 views
24

用KnockoutJS分条列表的最佳方式是什么?下面div中的类应该是偶数或奇数,取决于它在列表中的位置,并在添加或删除项目时进行更新。将条纹样式添加到项目列表中

<div class="Headlines loader" 
    data-bind="css: { loader: headlines().length == 0 }, 
         template: { name: 'recentHeadlinesTemplate', 
            foreach: beforeHeadlineAddition, 
            beforeRemove: function(elem) { $(elem).slideUp() }, 
            afterAdd: slideDown }"> 
</div> 

<script type="text/html" id="recentHeadlinesTemplate"> 
    <div class="even"> 
     ${Title} 
    </div> 
</script> 

回答

21

有这个就KO论坛上,而回到这里的话题:https://groups.google.com/d/topic/knockoutjs/cJ2_2QaIJdA/discussion

,我必须是一个自定义绑定解决方案。最近也有一对夫妇的变化,但它基本上看起来像:

ko.bindingHandlers.stripe = { 
    update: function(element, valueAccessor, allBindingsAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()); //creates the dependency 
     var allBindings = allBindingsAccessor(); 
     var even = allBindings.evenClass; 
     var odd = allBindings.oddClass; 

     //update odd rows 
     $(element).children(":nth-child(odd)").addClass(odd).removeClass(even); 
     //update even rows 
     $(element).children(":nth-child(even)").addClass(even).removeClass(odd);; 
    } 
} 

和使用,如:这里

<ul data-bind="template: { name: 'itemsTmpl', foreach: items }, stripe: items, evenClass: 'light', oddClass: 'dark'"></ul> 

样品与此结合的3个变化:

http://jsfiddle.net/rniemeyer/HJ8zJ/

+0

如何确保在应用条纹之前完成模板渲染?或者甚至是一个问题? – neebz

+1

只需要在模板绑定后加上'stripe'绑定就可以了。绑定确实从左到右运行,但史蒂夫已经说过,这不是他想要保证的东西。否则,在小提琴中有一个名为'templateWithStripe'的版本,它封装了模板绑定并绝对保证了顺序。它可能提供了最简单的语法。 –

+0

我看到了这个,但我希望有一个更简单的方法。我想我会和这一起去的。 –

0

您可以使用{{if}}{{else}}条件语句在模板中设置类的div。

此外,您还需要扩展视图模型以包含一个函数,该函数返回当前项目的索引,它会告诉您它是奇数还是偶数。 (Something like this

+0

这可能适用于静态列表,但如果我删除并添加项目,那么我可以在一行中有两个偶数或奇数行。 –

+0

我认为在添加/删除数组中的某些东西时,knockoutjs会重新渲染整个模板 – neebz

3

这样做的一个简单方法是添加一个计算的可观察值,为每个元素添加一个索引,例如

self.logLines = ko.observable(logLinesInput); 

    self.enhancedLogLines = ko.computed(function() { 
     var res = []; 
     $.each(self.logLines(), function(index, ll) { 
      res.push(new LogLine(index, ll)); 
     }); 
     return res; 
    }, self); 

在我的情况​​将创建一个索引字段,并且均在原始对象的其它字段的对象。

现在你可以斑马条纹轻松地添加到您的输出:

  <tr data-bind="css: { odd: (index % 2 == 1), even: (index % 2 == 0) }"> 
55

我发现用foreach迭代时,返回索引的功能,这样你就可以在一个相当紧凑的方式应用偶数和奇数类,例如:

<tr data-bind="css: { 'even': ($index() % 2 == 0) }"> 
+4

$ index记录在绑定上下文中:[链接](http://knockoutjs.com/documentation/binding-context.html) - 谢谢@wesc – ZiglioUK

+3

这一直一直是我的首选方法,我没有看到它与接受的答案相比没有提供什么。 –

+1

谢谢,我认为接受的答案会在我的答案发布之前发布,因此除非原始发布者评论它,否则它将保持原样。不知道是否有人可以改变这一点 – ZiglioUK

0

这里是一个完整的例子:

<ul class="pickupPointHours" data-bind="foreach: Items"> 
<li data-bind="css: { lineEven: ($index()%2 === 0), lineOdd: ($index()%2 === 1)}"> 
    <span class="pickupPointDay" data-bind="text: TextProperty"></span> 
</li> 
</ul> 
2

感谢FO r有用的帖子。我想提到的是,CSS可以很好地进行条带化处理,但嵌入的“if”似乎只能在行被渲染后才起作用。因此,使用$ index或css odd/even功能不会产生所需的结果。在不使用模板的情况下,我发现你可以在行的周围包装KO逻辑,以便在行被计数之前发生逻辑。

<tbody data-bind="foreach: viewModel.configuration().items()""> 
    <!-- ko if: $data.part() != '' --> 
    <tr> 
      <td data-bind="text: $index"></td><td data-bind="text: $data.part()"></td> 
    </tr> 
    <!-- /ko --> 
</tbody>