1

我有一个由构造函数创建的视图模型,具有一堆可观察的属性和一堆普通的旧属性。一旦我实例化它,如果我在实例上设置一个值,对该值的更改不会反映在计算的 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" :/

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

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

我当然可以使 active 成为 observable,但我想知道是否有另一种方法可以做到这一点。

4

3 回答 3

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>

如您所见,这不是很有用。总的来说,更多的 observables 对你的应用程序性能的影响不会超过几微秒。我的建议是推迟优化你的代码,直到你发现问题。您的用户更有可能看到循环评估或大型 AJAX 负载变慢,而不是一些使您的代码更易于编写的可观察对象。

我希望这有帮助!

于 2013-07-17T01:51:25.097 回答
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其定义为可观察的。

于 2013-07-16T20:38:55.843 回答
0

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

于 2013-07-16T20:37:22.060 回答