我正在使用KnockoutJS并尝试订阅位于observable
的{{1}}中的observableArray
。所以我的viewModel看起来像这样......
observableArray
从映射插件中填充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
我正在尝试设置订阅UserMovies.Rating但是,从我上面的viewModel获取错误消息
TypeError:self.movies.UserMovies未定义
如果从映射插件中填充[{
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 }]
}]
,我将如何设置订阅?
答案 0 :(得分: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);
});
});
});
按预期处理添加,更新和删除。
答案 1 :(得分:2)
我认为你必须循环播放你的电影并订阅每个人的评级属性:
$.each(self.movies(), function(i, movie) {
movie.Rating.subscribe(function(newRatingValue){ /* ... */ })
});
当然,这里的缺点是您还必须订阅阵列本身,以及在阵列中添加新电影的情况,然后手动订阅他们的评级中的更改价值也是如此。
答案 2 :(得分: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评级订阅。我没有测试过。我只在单个对象而不是对象数组中使用它。