刚刚发现,KnockoutJS订阅函数在依赖计算机之前进行评估,需要有人可以提交,因为我无法在文档或论坛中找到关于Knockouts时序的任何内容。
这意味着:如果我有这样的模型......
var itemModel = function (i) {
var self = this;
self.Id = ko.observable(i.Id);
self.Title = ko.observable(i.Title);
self.State = ko.observable(i.State);
};
var appModel = function () {
var self = this;
self.Items = ko.observableArray() // <-- some code initializes an Array of itemModels here
self.indexOfSelectedItem = ko.observable();
self.selectedItem = ko.computed(function () {
if (self.indexOfSelectedItem() === undefined) {
return null;
}
return self.Items()[self.indexOfSelectedItem()];
});
};
我想跟踪一个带有可观察索引字段的所选数组项,我订阅这个索引字段就像这样......
appModel.indexOfSelectedItem.subscribe(function () {
// Do something with appModel.selectedItem()
alert(ko.toJSON(appModel.selectedItem()));
}
...在使用新索引值重新评估计算之前评估订阅函数,因此我将获得与最后选择的索引对应的selectedItem(),而不是实际选择的索引。
两个问题:
答案 0 :(得分:3)
默认情况下,Knockout中的所有计算都是以急切的方式评估,而不是懒惰(即,首次访问时不)。
只要一个依赖项发生更改,就会通知所有订阅,并重新评估所有连接的计算。您可以通过在计算的observable中指定the deferEvaluation
option将该行为更改为“lazy”,但不能对订阅执行此操作。
Hoewever,我认为没有必要依赖所选项目的索引。事实上,这甚至是糟糕的设计,因为你不是真正在索引的数值中,而是在它所代表的项目中。
您可以通过创建可写的计算observable来反转依赖关系,该observable为您提供当前所选项目的索引(用于显示目的)并允许更改它(为方便起见)。
function AppModel() {
var self = this;
self.Items = ko.observableArray();
self.selectedItem = ko.observable();
self.indexOfSelectedItem = ko.computed({
read: function () {
var i,
allItems = self.Items(),
selectedItem = self.selectedItem();
for (i = 0; i < allItems.length; i++) {
if (allItems[i] === selectedItem) {
return i;
}
}
return -1;
},
write: function (i) {
var allItems = self.Items();
self.selectedItem(allItems[i]);
}
});
}
Knockout倾向于存储/处理实际值而不仅仅是索引值,因此对视图进行必要的更改可能并不困难。只需将以前写入indexOfSelectedItem
的所有内容直接写入selectedItem
即可。 selectedItem
的依赖关系将继续正常运作。
在精心设计的Knockout应用程序中,您很少需要处理数组项的索引。一旦一切正常,我建议删除计算的write
部分。