繁体   English   中英

Knockout计算与订阅,时间问题

[英]Knockout computed vs. subscription, timing issues

刚刚发现,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(),而不是实际选择的索引。

两个问题:

  • 是对的吗?
  • 那么为什么我应该使用ko.computed()如果一个简单的函数每次调用它时都会获取当前所选项目,而ko.computed会在任何时候进行评估,而且我已经完成所有事情了,我不再需要它了?

默认情况下,在淘汰赛的所有computeds在热切的方式进行评估,而不是懒洋洋地(即, 不是当你第一次访问它们)。

只要一个依赖项发生更改,就会通知所有订阅,并重新评估所有连接的计算。 您可以通过在计算的observable中指定deferEvaluation选项将该行为更改为“lazy”,但不能对订阅执行此操作。

Hoewever,我认为没有必要依赖所选项目的索引。 事实上,这甚至是糟糕的设计,因为你并没有真正融入索引的数值,而是在它所代表的项目中。

您可以通过创建可写的计算observable来反转依赖项,该observable为您提供当前所选项目的索引(用于diplay目的)并允许更改它(为方便起见)。

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部分。

请参阅: http//jsfiddle.net/4hLLn/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM