5

KnockoutJSを使用していて、にあるをサブスクライブしようとしてobservableobservableArrayます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);
    });
}

observableArrayは、マッピングプラグインから入力されると次のmoviesようになります...

[{
    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からエラーメッセージが表示されます

TypeError:self.movi​​es.UserMoviesは未定義です

UserMovies.Ratingマッピングプラグインからサブスクリプションが入力されたときにサブスクリプションを設定するにはどうすればよいですか?

4

3 に答える 3

7

Knockoutは、配列内でどのアイテムが変更されたかを知るための粒度を提供しません。何かが変更されただけです。アイテムが追加または削除されるたびに、配列をループする必要があります。

foreachバインディング(via )は、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 || "");
        }
    });

オブジェクト内のものをサブスクライブすることで何ができるか、できないかはわかりませんが、これは機能します。また、各サブスクリプションが一意であるかどうか、または1つのレーティングの変更によってすべてのUserMoviesレーティングサブスクリプションが無効になるかどうかもわかりません。私はそれをテストしていません。私はこれを単一のオブジェクトでのみ使用し、オブジェクトの配列では使用していません。

于 2016-04-15T12:12:06.697 に答える