如何在observableArray中订阅observable

bfl*_*mi3 5 javascript knockout.js

我使用KnockoutJS并试图订阅的observable是在observableArray是在observableArray.所以我的viewModel看起来像这样......

function viewModel() {
    // private properties
    var self = this;

    // public properties
    self.movies = ko.mapping.fromJS([]);

    // subscriptions
    self.movies.UserMovies.Rating.subscribe(function(newValue) {
        console.log(newValue);
    });
}
Run Code Online (Sandbox Code Playgroud)

moviesobservableArray应该是这样的,一旦从映射插件填充...

[{
    Id: 1,
    Title: 'Movie1',
    Year: 2010,
    UserMovies: [{ Id: 11, Rating: 3.5, IsWatched: true }]
},{
    Id: 2,
    Title: 'Movie2',
    Year: 2010,
    UserMovies: [{ Id: 4, Rating: 4, IsWatched: true }]
}]
Run Code Online (Sandbox Code Playgroud)

我正在尝试设置UserMovies.Rating的订阅,但是,从我上面的viewModel获取错误消息

TypeError:self.movi​​es.UserMovies未定义

我如何设置订阅UserMovies.Rating从映射插件填充的时间?

Mar*_*rot 7

Knockout没有提供粒度来知道数组中哪些项更改,只是更改了一些内容.每次添加或删除项目时,您都需要循环遍历数组.

foreach(通过结合ko.utils.compareArrays)实际上计算操作的最小数量,以一个阵列变换为另一个,使得DOM元素不需要被重新创建.

使用ko.utils.compareArrays,我能够创建一个订阅项目级别的数组更改的方法.利用这个,我可以编写一个select管理订阅的方法.

http://jsfiddle.net/MizardX/s9M4z/

使用新select方法,您可以非常简洁地执行此操作:

// Subscribe to items added to the array. The returned 'subscription' will be
// disposed of, when the item is later removed.
viewModel.movies.select(function (movie) {

    // Return the subscription. Same as above.
    return movie.UserMovies.select(function (userMovie) {

        // Subscribe to a non-array. The callback will receive the updated value,
        // instead of the an added item.
        return userMovie.Rating.select(function (rating) {

            // Executed each time a rating is updated.
            console.log(movie.Id(), userMovie.Id(), rating);
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

它按预期处理添加,更新和删除.