【问题标题】:Knockout Subscribe to any change in observable complex objectKnockout 订阅可观察的复杂对象的任何变化
【发布时间】:2015-01-17 01:54:56
【问题描述】:

我有一个包含一个可观察对象的视图模型,它是用一个对象初始化的。 此对象本身包含可观察对象。

我的目标是在该对象发生更改时(或:当该对象中的任何可观察对象发生更改时)得到通知

jsfiddle

复杂对象

var ns = ns || {};

ns.ComplexObj = function (item) {
    var self = this;

    if (!item) {
        item = {};
    }

    self.id = item.Id || '';
    self.company = ko.observable(item.Company || '');
    self.email = ko.observable(item.Email || '');

    self.company.subscribe(function () {
       console.log('debug: company changed');
    });

    return self;
};

视图模型

ns.mainvm = function () {
   var simpleObject = ko.observable('i am pretty simple');

   simpleObject.subscribe(function (newValue) {
       document.getElementById('simpleSubscribtionFeedback').innerText = newValue;
   });

   var complexObject = ko.observable(ns.ComplexObj());
   complexObject.subscribe(function (newValue) {
       // i would like to react to any change in complex object
       document.getElementById('complexSubscribtionFeedback').innerText = 'i dont get executed :(';
   });

   return {
       simpleObject: simpleObject,
       complexObject: complexObject
   };
};

绑定

var container = document.getElementById('wrapper');
if (container) {
   ko.applyBindings(ns.mainvm, container);
} else {
   console.warn("container for binding ko not found");
}

是否有可能对复杂对象的更改做出反应?任何帮助表示赞赏。

我已经尝试了来自 rpniemeyer 的dirtyFlag 解决方案(cmets 中的链接)。复杂对象上的脏标志的问题是,当它切换到“真”并且我正在订阅该标志时,这只是第一次可以。为了对进一步的变化做出反应,我需要再次将dirtyFlag设置为false(在订阅中完成我的工作之后)。这将导致订阅循环。

【问题讨论】:

标签: knockout.js


【解决方案1】:

您可以使用以下技巧:

ko.computed(function() {
    return ko.toJSON(complexObject);
}).subscribe(function() {
    // called whenever any of the properties of complexObject changes
});

http://jsfiddle.net/xcajt4qn/3/

之所以可行,是因为ko.toJSON会递归读取对象中的所有属性,从而使计算依赖于所有属性。

【讨论】:

  • 请注意,只要对象的任何 可观察属性发生变化,这也将被调用,这可能是不需要的。
  • @tloflin 怎么样?不会对这些属性进行任何更改跟踪
  • 提示:将 console.log 放入 subscribe 以检查它没有被调用太多次。您可以使用可观察的速率限制来避免过多的事件,如果字段是文本输入,这尤其有用。针对这种情况,在 subscribe 函数之前添加 extend({ rateLimit: 500 })。我相信 rateLimit: 0extend({ deferred: true }); 可能会很有用,如果您发现每次更改都会引发多个事件。
  • 有没有一种简单的方法来确定哪个属性引发了更改事件?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-02
  • 1970-01-01
  • 1970-01-01
  • 2020-06-28
  • 2020-09-16
  • 2022-01-23
  • 2018-07-28
相关资源
最近更新 更多