迭代对象knockoutjs的属性

时间:2013-03-11 18:33:22

标签: javascript knockout-2.0

从我在网上找到的内容来看,我认为不可能使用foreach data-bind来遍历knockout中可观察对象的属性。

如果有人可以帮我解决我想要做的事情,我会非常感激。

假设我有一系列电影对象:

var movies = [{
    title: 'My First Movie',
    genre: 'comedy',
    year: '1984'    
},
{
    title: 'My Next Movie',
    genre: 'horror',
    year: '1988'
},
];

我想要做的是在表格中显示这些数据,但每种类型的电影都有不同的表格。

所以我尝试过这样的事情:

<div data-bind="foreach: movieGenre">
    <table>
        <tr>
            <td data-bind="year"></td>
            <td data-bind="title"></td>
            <td data-bind="genre"></td>
        </tr>
    </table>
</div>

我的数据源更改为:

for (var i = 0; i < movies.length; ++i) {
    if (typeof moviesGenres[movies.genre] === 'undefined')
        moviesGenres[movies.genre] = [];
    moviesGenres[movies.genre].push(movie);
}

我已经尝试了十几个其他的解决方案,我开始怀疑这是否是我缺乏淘汰赛的知识(我还是很绿),或者说我不喜欢这样的方式它是。

1 个答案:

答案 0 :(得分:0)

您可以使数组“movies”成为KO可观察数组,数组“movieGenre”成为KO计算属性。看看this fiddle

为了方便读者,下面给出了小提琴中的代码;

KO View Model

function MoviesViewModel() {
    var self = this;
    self.movies = ko.observableArray([
        {
            title: 'My First Movie',
            genre: 'comedy',
            year: '1984'
        },
        {
            title: 'My Next Movie',
            genre: 'horror',
            year: '1988'
        },
        {
            title: 'My Other Movie',
            genre: 'horror',
            year: '1986'
        }
    ]);

    self.movieGenre = ko.computed(function() {
        var genres = new Array();

        var moviesArray = self.movies();
        for (var i = 0; i < moviesArray.length; i++) {
            if (genres.indexOf(moviesArray[i].genre) < 0) {
                genres.push(moviesArray[i].genre);
            }
        }

        return genres;
    });  
};

HTML

<div data-bind="foreach: movieGenre()">
    <h3 data-bind="text: 'Genere : ' + $data"></h3>
    <table border="solid">
        <thead>
            <tr>
                <th>Title</th>
                <th>Genre</th>
                <th>Year</th>
            </tr>
        </thead>
        <tbody data-bind="foreach: $parent.movies">
            <!-- ko if: $data.genre === $parent -->
            <tr>
                <td data-bind="text: $data.title"></td>
                <td data-bind="text: $data.genre"></td>
                <td data-bind="text: $data.year"></td>
            </tr>
            <!-- /ko -->
        </tbody>
    </table>
</div>

正如您所看到的,“movieGenre”是一个计算属性。每当可观察数组“电影”发生变化时,就会计算并缓存moveGenre。但是,由于未将其声明为可写计算属性,因此无法将其绑定到视图。因此,它的值用于数据绑定。

渲染方法只是循环计算出的“movieGenre”,并为电影嵌套另一个循环。在向表中添加行之前,对于相应的表,将使用当前的movieGenre计算影片对象。这里,使用无容器控制流语法。我们可以使用“if”绑定,但是每个电影对象都会留下一个空表行,否则就会出现类型。

$ parent绑定上下文用于访问嵌套循环中的父上下文。

希望这有帮助。