观察可观察

时间:2017-04-11 21:17:42

标签: typescript knockout.js knockout-3.0

我正在使用KnockoutJS 3.4。

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

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

ItemViewModel包含一堆可观察的属性。其中包括IdNameDescription

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

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

编辑我已阅读评论及相关问题。它不识别已更改的属性。我已经更新了这个问题以反映这一点。

1 个答案:

答案 0 :(得分:2)

为了确定修改了哪个属性,您需要一个不太通用的解决方案。您可以通过将扩展程序附加到需要跟踪的每个属性来执行此操作。我希望扩展程序接受可订阅的视图模型级别,以及要扩展的属性的名称。 (遗憾的是,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 }})
    }
}