Knockout:构造函数中的计算Observable忽略对实例的更改

时间:2013-07-16 20:31:07

标签: knockout.js

我有一个viewmodel,它是一个由构造函数创建的,具有一堆可观察的属性和一堆普通的旧属性。一旦我实例化它,如果我在实例上设置一个值,那么对该值的更改不会反映在计算的observable中。

这是我所看到的精炼版本:

function ViewModel(active) {
    var self = this;
    self.active = active;

    self.getClasses = ko.computed(function () {
        return this.active ? "yup" : "nope";
    }, self);
}

var vm = new ViewModel(false);
vm.active = true;

alert(vm.getClasses()); //returns "nope" :/

如果我触摸它所依赖的可观察量,这个计算出的observable将重新进行评估,但直接调用它会导致使用旧的active值进行评估。

ko.computed是否创建了一个忽略对父级更新的新闭包?将普通值与可观察值混合是不明智的吗? (我实际上遇到的问题是依赖于observables和其他属性,但我不希望其他属性在运行时更改。这实际上只是我单元测试中的一个问题。)

我当然能激活一个可观察的,但我想知道是否还有另一种方法可以做到这一点。

3 个答案:

答案 0 :(得分:3)

Josh,在ko.computed内部立即执行您的计算函数并存储结果,直到某些操作要求它重新计算自身(如订阅可观察的更改)。这种内部缓存可能会带来巨大的性能提升;如果没有订阅的值已更改,则无需重新运行计算,因为结果应该相同。

这就是为什么计算所依赖的任何值都被创建为可观察值的原因。

目前无法强制计算机按需重新计算,因为这通常表明您的架构存在问题。如果您需要一个按需计算但不依赖任何observable的值,那么常规函数将是实现这一目标的最佳方法。

self.getClasses = function () {
      return self.active() ? "yup" : "nope";
  };

虽然您需要在绑定表达式中添加括号,但您可以绑定UI以显示与计算函数相同的常规函数​​的结果。请记住,这只会在绑定时显示功能的结果。如果您的计算发生变化,UI将不会保持最新状态;因为你需要一个ko.computed。

<!-- this will only show the value at bind-time and never be updated -->
<div data-bind="text: getClasses()"></div>

如您所见,这不是很有用。总的来说,一些更多的可观察量不太可能影响您的应用程序性能超过几微秒。我的建议是在看到问题之前推迟优化代码。与使一些代码更容易编写的一些可观察对象相比,您的用户更有可能看到循环评估或大型AJAX有效负载减慢。

我希望这有帮助!

答案 1 :(得分:1)

您是否尝试过像这样设置可观察值:

function ViewModel(active) {
  var self = this;

  self.active = ko.observable(active);

  self.getClasses = ko.computed(function () {
      return this.active() ? "yup" : "nope";
  }, self);
}

var vm = new ViewModel(false);
vm.active(true);

因此将observable设置为函数(括号之间的值),而不是像属性一样。并确保将active定义为可观察的。

答案 2 :(得分:0)

如果您希望通知(并在计算中评估)此变量的更改,则Active必须是可观察的。