5

observable我正在observableArray使用KnockoutJS 并尝试订阅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);
    });
}

从映射插件填充后,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 }]
}]

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

类型错误:self.movi​​es.UserMovies 未定义

UserMovies.Rating当从映射插件填充它时,我将如何设置订阅?

4

3 回答 3

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);
        });
    });
});

它按预期处理添加、更新和删除。

于 2012-12-21T00:28:46.350 回答
2

我认为你必须遍历你的电影并订阅每个人的评级属性:

$.each(self.movies(), function(i, movie) { 
     movie.Rating.subscribe(function(newRatingValue){  /* ... */ }) 
});

当然,这里的缺点是您还必须订阅数组本身,以应对将新电影添加到数组中的情况,然后手动订阅评分值的更改。

于 2012-12-20T21:30:11.840 回答
0

您可以以这种方式订阅您的属性:

   var UserMovies = function (data) {
        this.Id = ko.observable();
        this.Rating = ko.observable();
        this.IsWatched = ko.observable();
        this.update(data);
    }

    ko.utils.extend(UserMovies.prototype, {
        update: function (data) {
            this.Id(data.Id || "");
            this.Rating(data.Rating || "");
            this.Rating.subscribe(function (newValue) {
                console.log(newValue);
            });
            this.IsWatched(data.IsWatched || "");
        }
    });

我不确定通过订阅对象内部的东西可以做什么或不做什么,但这确实有效。我也不确定每个订阅是否都是唯一的,或者一个评级更改是否会引发所有 UserMovies 评级订阅。我没有测试过。我只在单个对象而不是对象数组中使用它。

于 2016-04-15T12:12:06.697 回答