Knockout 订阅可观察的复杂对象的任何变化

Posted

技术标签:

【中文标题】Knockout 订阅可观察的复杂对象的任何变化【英文标题】:Knockout Subscribe to any change in observable complex object 【发布时间】: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(在订阅中完成我的工作之后)。这将导致订阅循环。

【问题讨论】:

This post 可能会帮助您入门。 这个插件似乎完全符合你的要求:github.com/ZiadJ/knockoutjs-reactor 【参考方案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 ); 可能会很有用,如果您发现每次更改都会引发多个事件。 有没有一种简单的方法来确定哪个属性引发了更改事件?

以上是关于Knockout 订阅可观察的复杂对象的任何变化的主要内容,如果未能解决你的问题,请参考以下文章

Knockout.js:当可观察数组中的值发生变化时触发计算的最佳方法是啥

在 knockout.js 中更改 observable 但不通知订阅者

循环遍历具有可观察属性的 Knockout 可观察对象数组

Knockout JS 订阅 2 个 observables 的方式是,如果 2 个 observables 中的任何一个发生变化,我只会收到一次通知

Knockout JS - 在没有 ko.mapping 的情况下观察数组的任何属性中的突变

订阅可观察对象返回未定义