2015-07-21 67 views
3

我想用JS淘汰赛foreach循环来构建以下HTML ...将容器放置在周围淘汰赛JS foreach循环每个“N”项目

<div> 
    <div> 
    <article></article> 
    <article></article> 
    <article></article> 
    </div> 
    <div> 
    <article></article> 
    <article></article> 
    <article></article> 
    </div> 
</div> 

...,其中每个“文章”是数组中的一个项目。

我试过以下,这似乎逻辑上的声音,但它不工作 - 我假设的淘汰赛是越来越由不平衡标签注释里面迷茫......

<div data-bind="foreach: articles()"> 
    <!-- ko: if ($index() % 3 == 0) 
    <div> 
    <!-- /ko --> 

    <article></article> 

    <!-- ko: if ($index() % 3 == 2) 
    </div> 
    <!-- /ko --> 
</div> 

有什么想法关于如何实现这一点将不胜感激!

+0

我有同样的问题,只是用'thead'和'tbody'我显然只是想创造一次的基础上,$指数()。 KO只能照顾形态良好的元素。请注意,在绑定中使用括号将从您的视图中的数据绑定中移除自动更新:'foreach:articles()'。只需去'foreach:articles'。 – connexo

回答

1

我在解决类似问题时一直认为视图模型必须尽可能地与视图紧密结合,以便在视图本身中不执行逻辑。因此,因此这个地方,以便将物品阵列在视图模型使用ko.computed建立如下的结构:

groupedArticles = [ 
    [article1, article2, article3], 
    [article4, article5, article6] 
] 

那么在你看来,你可以这样做:

<!-- ko foreach: groupedArticles --> 
<div> 
    <!-- ko foreach: $data --> 
    <article></article> 
    <!-- /ko --> 
</div> 
<!-- /ko --> 

让我知道这是否有意义与否;如果没有,我可以尝试添加小提琴来演示它。

更新

我发现了用这种模式的小提琴。我需要KO升级到最新版本,以获得它的工作,你现在可以使用这个试试吧:http://jsfiddle.net/hFPgT/160/

这是问题,How to get Knockout to group foreach

及相关代码:

this.grouped = ko.computed(function() { 
     var rows = [], current = []; 
     rows.push(current); 
     for (var i = 0; i < this.items.length; i += 1) { 
      current.push(this.items[i]); 
      if (((i + 1) % 4) === 0) { 
       current = []; 
       rows.push(current); 
      } 
     } 
     return rows; 
}, this); 
+0

虽然这可行,但它并不漂亮,因为它将显示逻辑与数据混合在一起。 – Nit

+0

你能解释一下吗?毕竟,视图模型并不完全是一种模型。这个模型适应了适合在视图中渲染的结构。因此,根据其定义,它是显示逻辑与数据混合的地方。如果你想获得更多的分离,所有手段都有单独的模型,然后是视图模型和视图。像击倒这样的框架可以做到这一点。 – sifriday

+0

通过MVVM范例,数据应该存储在模型中,修改后供视图模型查看并由视图显示。所以正确的做法是建立一个单独的模型,然后在视图模型中使用这些数据。 – Nit

1

像@sifriday,我会去一个单独的计算数组,我会叫articleGroups(或查看)。在我最近对Knockout的理解中,我发现将所有视图相关的逻辑(这里:分组)放在组件的viewModels中是最方便的,所以我在这里为它构建了一个组件。 额外的好处是您可以在视图中传递参数;例如,尝试使用以下代码段中的“groupBy”不同的值。

// setup 
 
var articles = []; 
 
for (var i = 0; i < 50; i++) 
 
    articles.push({i: i+1, text: "text"}); 
 

 
// listview component 
 
ko.components.register('article-view', { 
 
    viewModel: function(params) { 
 
    var groupBy = this.groupBy = ko.observable(params.groupBy); 
 
    this.articleGroups = ko.computed(function() { 
 
     var result = [], group = groupBy(); 
 
     ko.utils.arrayForEach(ko.unwrap(params.data), function(item, index) { 
 
     if (index % group === 0) 
 
      result.push([item]); 
 
     else 
 
      result[result.length-1].push(item); 
 
     }); 
 
     return result; 
 
    }); 
 
    }, 
 
    template: {element: 'article-group'} 
 
}); 
 

 
// viewModel instantiation 
 
VM = { articles: ko.observableArray(articles)}; 
 
ko.applyBindings(VM);
body>div>div>div { border-bottom: 1px solid gray; padding-bottom: 10px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script type="text/template" id="article-group"> 
 
    <input type="number" data-bind="value: groupBy" min="1" max="50"> 
 
    <div data-bind="foreach: articleGroups, as: 'group'"> 
 
    <div data-bind="foreach: $data, event: {load: console.log($data)}"> 
 
     <article data-bind="text: i"></article> 
 
    </div> 
 
    </div> 
 
</script> 
 
<div data-bind="component: {name: 'article-view', params: {groupBy: 5, data: articles}}"></div>