Knockout计算的observable在更改其依赖关系时不会更新值

Knockout computed observable is not updating value when changing its dependencies

本文关键字:关系 更新 依赖 计算 observable Knockout      更新时间:2023-09-26

我一直在寻找解决方案,但在任何地方都找不到。我正试图创建一个ko.computed,它依赖于另外两个可观察性。每当可观察到的变化时,我都希望我计算出的可观察到也能更新,但事实并非如此。当我更改计算函数的任何依赖项时,它不会更新(视图+变量本身)。还有另一个可以与这个问题联系起来的问题。为什么"自我"变量是全球性的?即使我从AppViewModel中删除了它,它仍然是全局的。

这是一个简短的版本,下面你可以找到一个完整的工作示例的JSFiddle。当你按下"攻击"时,你的力量应该从5增加到1000,这反过来会将进度条"maxExp"值从0/6更新到一些高值0/500或其他值。

function AppViewModel() {
var self = this;
player = new playerTest();
enemies = new enemiesTest();
activeEnemy = new initializeFirstEnemy();
console.log('Call me more pls');
};
var baseStatsArray = ['Strength', 'Endurance', 'Speed', 'Luck'];
var currentEnemy = ko.observable(0);
function playerTest() {
   var self = this;
   var value;
   var growth;
   this.baseStats = {};
for (var i = 0; i < baseStatsArray.length; i++) {
    var attr = baseStatsArray[i];
    this.baseStats[attr] = {};
    this.baseStats[attr]['value'] = ko.observable(5);
    this.baseStats[attr]['growth'] = ko.observable(2);
    this.baseStats[attr]['minExp'] = ko.observable(0);
    this.baseStats[attr]['maxExp'] = ko.computed(function () {
        return Math.floor((10 + (self.baseStats[attr]['value']() / 2)) / self.baseStats[attr]['growth']());
    });
};
};

https://jsfiddle.net/tuswdahc/1/

问题是,您试图在循环中创建计算,由于闭包和变量作用域的工作方式,您没有创建正确的计算。

有关更多信息,请参阅:

  • JavaScript闭包是如何工作的
  • 不要在循环中生成函数

一些可能的解决方案:

使用ko.utils.forEach或本机array.forEach而不是for循环:

ko.utils.arrayForEach(baseStatsArray, function(attr) {
    self.baseStats[attr] = {};
    self.baseStats[attr]['value'] = ko.observable(5);
    self.baseStats[attr]['growth'] = ko.observable(2);
    self.baseStats[attr]['minExp'] = ko.observable(0);
    self.baseStats[attr]['maxExp'] = ko.computed(function () {
        return Math.floor((10 + (self.baseStats[attr]['value']() / 2)) / 
            self.baseStats[attr]['growth']());
    });
});

将计算的创建移动到一个单独的函数中:

for (var i = 0; i < baseStatsArray.length; i++) {
    var attr = baseStatsArray[i];
    self.baseStats[attr] = {};
    self.baseStats[attr]['value'] = ko.observable(5);
    self.baseStats[attr]['growth'] = ko.observable(2);
    self.baseStats[attr]['minExp'] = ko.observable(0);
    self.baseStats[attr]['maxExp'] = createMaxExp(attr, self);
 };
function createMaxExp(attr, self) {
    return  ko.computed(function () {
        return Math.floor((10 + (self.baseStats[attr]['value']() / 2)) /   
            self.baseStats[attr]['growth']());
    });
 }

演示JSfiddle。

关于"全局"自身的问题:您没有正确创建视图模型,因为在调用applyBindings时缺少new

所以改变

 ko.applyBindings(AppViewModel);

ko.applyBindings(new AppViewModel());