在foreach循环中分配值

时间:2013-02-14 21:19:50

标签: knockout.js

想象一下按名称排序的联系人数组。 该数组可以输出如下:

<ul data-bind="foreach: contacts>
    <li data-bind="text: name"></li>
</ul>

我想要做的是为每个具有不同起始字母的li指定标题,例如显示A,B,D ......

- A
- Anderson
- Andrews
- B
- Bellamy
- D
- Davidson
- Davis

在普通的编程语言中,我会定义一个包含名字第一个字母的变量,并在foreach循环中检查它是否不同。如果是这种情况,请显示标题。

我应该如何使用knockout.js?

2 个答案:

答案 0 :(得分:1)

这是一种坚持Knockout模式的方法。首先,您将创建一个计算的observable,将您的数组映射到一个按字母分组的新数组。

self.contactsByLetter = ko.computed(function () {
    var result = [],
        currentLetter, currentGroup;
    ko.utils.arrayForEach(self.contacts(), function (contact) {
        if (contact.name[0] !== currentLetter) {
            currentLetter = contact.name[0];
            currentGroup = {
                letter: currentLetter,
                contacts: []
            }
            result.push(currentGroup);
        }
        currentGroup.contacts.push(contact);
    })
    return result;
});

然后你的HTML只需要两个循环。

<ul data-bind="foreach: contactsByLetter">
    <li class="heading" data-bind="text: letter"></li>
    <!--ko foreach: contacts-->
    <li data-bind="text: name"></li>
    <!--/ko-->
</ul>

jsFiddle:http://jsfiddle.net/mbest/ZcQT4/

答案 1 :(得分:0)

不确定它是否更清晰,但您可以使用固定数组作为字母,然后在视图模型上使用方法仅返回以第n个字母开头的项目 - 即

<ul data-bind="foreach: letters">
    <li data-bind="text: $data">
        <ul data-bind="foreach: $parent.contactsStartingWith($data)">
             <li data-bind="text: name"></li>
        </ul>
    </li>
</ul>

其中 contactsStartingWith 可以定义为:

function(start) {
    return ko.utils.arrayFilter(contacts(), function(it) { return it.name()[0].toUpperCase() == start } );
}

... 字母数组可以很容易地提取为:

viewModel.letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");

(使用数组的knockout工具的一些有用的参考:http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html