我有一个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和其他属性,但我不希望其他属性在运行时更改。这实际上只是我单元测试中的一个问题。)
我当然能激活一个可观察的,但我想知道是否还有另一种方法可以做到这一点。
答案 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必须是可观察的。