Knockout Computed Observable 在读取存储值后不更新

问题描述

我使用 Knockout 计算的 observable 以下列方式存储来自我的用户的数据:

var DummyClass = (function() {
   userPrefs = ko.observable({
      value1: 0,value2: 0,value3: 0});

   commonPrefs = ko.observable({
      required: false
   });

   var userSettings = ko.computed(function() {
      var value1 = userPrefs().value1;
      var value2 = userPrefs().value2;
      var value3 = userPrefs().value3;

      if (typeof value1 === 'undefined') {
         value1 = 0;
      }

      value1 = String(value1);

      if (value1.length === 0) {
         if (commonPrefs().required === true) {
            value2 = 0;
            value3 = 1;
         }
         else {
            value2 = 1;
            value3 = 0;
         }
      }

      return {
         value1: value1,value2: value2,value3: value3
      };
   }
}

如果我通过在代码中的其他地方使用 dummyClass.userSettings().value1 检索 value1,或使用新值更新它,任何进一步尝试通过 dummyClass.userSettings({value1: 1,value2: 2,value3: 3})(例如)将不再起作用,除非我重新加载我的网络应用程序,否则我在 userSettings 中拥有的任何值都将保持这种状态。

解决方法

几点:

  • 您的 userPrefs 是可观察的,但它的属性不是。所以KO不会知道他们是否被改变了。使用 KO 需要记住的一件事是你必须让一切都明确可见。不过,在这种情况下,如果您总是更新整个对象,您就不会这样做。
  • 默认情况下,计算变量不可写。如果这是你想要的,你必须明确地使它可写,但这不是你通常会做的事情(至少在我与 KO 合作的所有年里,我只遇到过一个有效的用例来计算可写;当然,这可能是个人喜好问题!)
  • typeof value1 = 'undefined' 是赋值而不是比较,因此不起作用。

这是一些示例代码,可以满足您的要求(我认为):

function ViewModel() {
    var vm = this;
    
    vm.userPrefs = ko.observable({
        value1: 0,value2: 0,value3: 0
    });
    
    vm.commonPrefs = {
        required: false
    };
    
    vm.userSettings = ko.pureComputed({
        read () {
            var value1 = vm.userPrefs().value1 || 0;
            var value2 = vm.userPrefs().value2;
            var value3 = vm.userPrefs().value3;

            if (value1 === 0) {
                if (vm.commonPrefs.required === true) {
                    value2 = 0;
                    value3 = 1;
                } else {
                    value2 = 1;
                    value3 = 0;
                }
            }

            return {
                value1,value2,value3
            };
        },write(newVal) {
            vm.userPrefs(newVal);
        }
    });
}

小提琴:https://jsfiddle.net/thebluenile/fqznpexg/

但是可写计算并不是真正必要的,因为您可以直接操作 userPrefsvm.userPrefs({ value1: 1,value2: 2,value3: 3})

,

您正在尝试为计算字段“userSettings”设置一个值,但您只定义了“读取”函数(不带参数)。为了通过这个属性设置一些值,你应该定义一个“写入”函数。见computed writable docs

除此之外,请注意,如果您有一个带有支持对象的 observable 字段(例如 DummyClass.userPrefs),您应该为“observable”函数提供一个新对象以更新该字段。

例如:

DummyClass.userPrefs().value1 = 1 - 不会触发 DummyClass.userPrefs 的更新

DummyClass.userPrefs({value1: 1,value3: 3}) - 将触发更新