【问题标题】:Observing all property changes within an observable观察可观察对象中的所有属性变化
【发布时间】:2017-09-07 10:57:24
【问题描述】:

我正在使用 KnockoutJS 3.4。

我的视图模型(TypeScript)如下所示:

export class ItemsViewModel {
    public currentItem: KnockoutObservable<ItemViewModel>;
    public items: KnockoutObservableArray<KnockoutObservable<ItemViewModel>>;
    /* snip */
}

ItemViewModel 包含一堆可观察的属性。这些包括IdNameDescription

我希望能够订阅currentItem 中发生的更改。使用 currentItem.subscribe 监视 currentItem 可观察值的变化,而不是当前项目中的属性。我已经看到另一个被建议为重复的问题,但它只是跟踪整个对象的更改 - 我想知道该对象的特定属性何时更改。

我怎样才能以最有效的方式做到这一点?

编辑我已阅读 cmets 和相关问题。它不识别更改的属性。我已更新此问题以反映这一点。

【问题讨论】:

  • 如果效率是指开发人员的时间,那么您可以创建一个计算属性,在您的视图模型上调用 ko.toJS。这将为视图模型中的每个可观察对象创建一个依赖项,然后您可以订阅该属性。
  • 为了完整起见,使用ko.toJS,您还可以仅跟踪视图模型某些部分的更改。
  • 关于可能的重复问题,如果这个问题是关于效率/速度的,我会在这里注意到 ko.toJS 比 ko.toJSON 性能更高
  • KnockoutObservableArray&lt;KnockoutObservable&lt;ItemViewModel&gt;&gt; 为什么要将observables 存储在observableArray 中?我建议不要这样做。

标签: typescript knockout.js knockout-3.0


【解决方案1】:

为了确定修改了哪个属性,您需要一个不太通用的解决方案。您可以通过将扩展程序附加到需要跟踪的每个属性来做到这一点。我会让扩展器接受一个可订阅通知的视图模型级别,以及被扩展的属性的名称。 (遗憾的是 JavaScript 没有反射来使该部分可编码)

ko.extenders.trackChange = function (target, options) {
    target.subscribe(function (newValue) {
        if (ko.isSubscribable(options.notifier)) options.notifier.notifySubscribers(options.propertyName);
    });
    return target;
};

然后在您的视图模型中添加可订阅和订阅。

self.propertyChanged = new ko.subscribable();
self.propertyChanged.subscribe(function(propertyName){
  console.log(propertyName + " was updated");
});

最后将扩展器添加到您的属性中。

self.property1 = ko.observable(0).extend({trackChange: { propertyName: 'property1', notifier: self.propertyChanged }});
self.property2 = ko.observable(0).extend({trackChange: { propertyName: 'property2', notifier: self.propertyChanged }});
self.property3 = ko.observable(0).extend({trackChange: { propertyName: 'property3', notifier: self.propertyChanged }});

如果您希望在每个属性上都使用它,您可以通过视图模型上的循环自动附加扩展器:

self.property1 = ko.observable();
self.property2 = ko.observable();
self.property3 = ko.observable();

for (key in self) {
    if (self.hasOwnProperty(key) && ko.isObservable(self[key])) {
        self[key].extend({trackChange: { propertyName: key, notifier: self.propertyChanged }})
    }
}

【讨论】:

  • 太棒了,这很有效,并且完全符合我的要求 - 非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-18
  • 2021-03-30
  • 2012-12-14
  • 1970-01-01
  • 2011-05-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多