Knockout订阅可观察复杂对象的任何更改

时间:2014-11-19 13:57:42

标签: knockout.js

我有一个viewmodel,它包含一个observable,用对象初始化。 这个对象本身包含了observables。

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

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解决方案(评论中的链接)。复杂对象上的脏标志的问题是,当它切换到" true"并且我已经挂上了那面旗帜的订阅,这只是第一次没问题。为了对进一步的更改作出反应,我需要再次将dirtyFlag设置为false(在订阅后执行我的操作)。这将导致订阅循环。

1 个答案:

答案 0 :(得分:46)

您可以使用以下技巧:

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将递归读取对象中的所有属性,因此使得计算依赖于所有属性。