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

时间:2015-12-31 14:22:08

标签: javascript knockout.js

我一直在寻找解决方案,但无法在任何地方找到它。我正在尝试创建一个ko.computed,它取决于另外两个observable。每当这个可观察的变化时,我希望我的计算的observable也能更新,但事实并非如此。当我更改任何依赖项时,计算函数不会更新(视图+变量本身)。还有一个问题可以解决这个问题。为什么“自我”变量全球化?即使我从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/

1 个答案:

答案 0 :(得分:3)

问题是你试图在循环中创建你的计算器,因为闭包和变量作用域的工作方式不能创建正确的计算。

有关详细信息,请参阅:

一些可能的解决方案:

使用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

关于“全局”自我的问题:你没有正确创建你的viewmodel,因为你在调用applyBindings时缺少new

所以改变

 ko.applyBindings(AppViewModel);

ko.applyBindings(new AppViewModel());