我遇到了一个问题,即我的计算的observable在一系列依赖项更改后停止触发。最后我发现了一点:如果在最近的评估期间依赖关系在假分支语句中,那么即使条件在评估完成之前变为真,也不会触发计算。 以下是一个示例:https://jsfiddle.net/sgs218w0/1/
var viewModel = new function(){
var self = this;
self.trigger = ko.observable(true);
self.fire = function(){
self.trigger(! self.trigger());
};
self.content = function(){
var test = 3;
return ko.computed(function(){
alert("triggered!");
if(test !== 0){
console.log(self.trigger());
alert(test);
}
test--;
});
}();
};
ko.applyBindings(viewModel);
是错误还是功能?你知道这个问题的解决方法吗?我似乎是优化,但对我来说它看起来很有侵略性和不正确。 (编辑:我改变主意。这是合理的,但有时会导致一些问题。我认为淘汰赛应该有解决这个问题的选择)
P.S。如果需要,我可以发布更详细的实际代码示例,以使问题更具体。但真正的代码点是一样的。
更新 好吧,我不得不懒得提供我想要实现的更详细的例子。我喜欢计算的想法,它会自动进行ajax调用。描述here。我看到的一个令人遗憾的是,即使UI的相应部分是不可见的,也会进行调用。我试着用这种方式修复它:https://jsfiddle.net/bpr88bp3/1/。问题是,一旦标签被去激活,它就不能被激活,因为计算停止触发......
答案 0 :(得分:3)
根据Knockout JS documentation:
因此,Knockout不仅仅是第一次检测到依赖关系 评估者运行 - 每次都重新检测它们。
当if(test !== 0){
为false时,由于在计算重新计算期间未调用self.trigger()
,Knockout不会订阅self.trigger()
。
如果没有订阅self.trigger()
,则不会重新计算已计算的self.trigger()
次更改。
恕我直言,解决方法是在任何情况下获得self.trigger()
(updated fiddle):
self.content = function(){
var test = 3;
return ko.computed(function(){
var triggerValue = self.trigger();
alert("triggered!");
if(test !== 0){
console.log(triggerValue);
alert(test);
}
test--;
});
}();
答案 1 :(得分:2)
一般来说,这个想法是计算出的observable的所有依赖关系也应该是可观察的。在您的情况下,self.content = function(){
var test = ko.obseravble(3);
return ko.computed(function(){
alert("triggered!");
if(test() !== 0){
console.log(self.trigger());
alert(test);
}
test(test()-1);
});
}();
不是可观察的;如果你可以观察它,你的代码应该按预期工作:
test
但是这引入了另一个问题,因为您现在正在更改计算的observable中的一个依赖项。通过逻辑地改变self.content = function(){
var respondToTriggerChange = ko.obseravble(3);
self.trigger.subscribe(function () {
respondToTriggerChange(respondToTriggerChange()-1);
});
return ko.computed(function(){
alert("triggered!");
if(respondToTriggerChange()){
console.log(self.trigger());
alert(test);
}
});
}();
,应该递归地计算计算值。如果计算是同步的,Knockout会阻止这种情况,但这不是一个真正的功能,它可能会在以后引起问题。
我认为这是一个更好的解决方案,可以正确隔离组件的含义:
apnsclient
答案 2 :(得分:2)
在阅读了您的问题的更新并查看更新的示例代码后,我想出了一个真正的解决方案。这使用pureComputed
进行更新,利用了可以通过订阅和处理订阅来激活和停用纯计算机这一事实。这是重要的代码:
updateComputed = ko.pureComputed(function () {
updateTrigger();
result(evaluator.call(owner));
});
ko.computed(function () {
var isActive = result.active();
if (isActive && !updateSubscription) {
updateSubscription = updateComputed.subscribe(function () {});
} else if (updateSubscription && !isActive) {
updateSubscription.dispose();
updateSubscription = undefined;
}
});