使用Knockout的'foreach'循环遍历多维数组

4
我有一个多维关联数组。
this.items = ko.observableArray([
    { name: "name1", viewable: true, children: [
        { name: "name1-1", viewable: true, children: []},
        { name: "name1-2", viewable: false, children: []}
    ] },
    { name: "name2", viewable: false, children: [] },
    { name: "name3", viewable: true, children: [
        { name: "name3-1", viewable: true, children: []},
    ] },
        { name: "name4", viewable: true, children: [] }
]);

目标是循环遍历这个数组并仅打印具有“viewable”设置为true的值。
我已经使用一堆if和foreach语句使其正常工作,但代码开始失控。此示例仅涵盖2级,但我的数组可以深达5级,因此此代码将迅速变得复杂而难看。
<ul data-bind="foreach: items">
    <!-- ko if: viewable -->
    <li data-bind="text: name"></li>
        <!-- ko foreach: children -->
            <!-- ko if: viewable -->
            <li data-bind="text: name"></li>
            <!-- /ko -->
        <!-- /ko -->
    <!-- /ko -->
</ul>

有没有更简单/更好的方法来循环整个数组? JS Fiddle 链接

你是否有一个适当的递归结构?例如,每个级别上的项目看起来是否相同?在你的示例中,一些children是缺失的,例如:{ name: "name1-1", viewable: true},这是一个要求吗? - nemesv
哦,那是一个打字错误。我可以控制它,所以我觉得最好还是包括'children',即使它是空的。我编辑了我的代码,并且在所有项目中添加了'children'。所以,是的,所有项目在所有层级上看起来都是一样的。 - dmathisen
3个回答

3

Underscore.js拥有一些优秀的处理数组的方法,也许您可以使用flattenfilter来从您的结构中创建一个数组,然后只需编写一个foreach

或者您可以使用模板来封装您的if: viewable逻辑,并递归应用模板:

<script type="text/html" id="template">
  <!-- ko if: viewable -->
    <li data-bind="text: name"></li>    
        <!-- ko template: { name: 'template', foreach: $data.children } -->
        <!-- /ko -->    
  <!-- /ko -->
</script>

<ul data-bind="template: { name: 'template', foreach: items } ">
</ul>

演示JSFiddle.


抱歉,Chris,nemesv 更快一些 - 我必须给他接受的答案。非常感谢大家的帮助!这使生活变得更加容易。 - dmathisen

1
你需要的是一个模板:

<script type="text/html" id="ItemTemplate">
    <!-- ko if: viewable -->
        <li data-bind="text: name"></li>
        <!-- ko template: { name: 'ItemTemplate', foreach: children } --><!-- /ko -->
    <!-- /ko -->
</script>

然后只需:

<ul data-bind="template: { name: 'ItemTemplate', foreach: items }"></ul>

1
如果在项目上添加空的子数组,您可以使用模板JSFiddle示例
<ul data-bind="foreach: items">
    <idv data-bind="template: {name: 'mytemp'}" />
</ul>
<div data-bind="stopBinding:true">
    <div id="mytemp">
        <div data-bind="visible :viewable">
            <li data-bind="text: name"></li>
            <div data-bind="foreach: children">
                <div data-bind="template: {name: 'mytemp'}" /></div>
        </div>
    </div>
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接