如何检测在手动订阅中调用的可观察属性

时间:2013-05-16 12:44:22

标签: knockout.js

有什么方法可以找出调用手动订阅的可观察属性的名称吗?

淘汰赛中的回调签名是.subscribe(function(newValue) { ... }),但由于我订阅了对象的所有可观察属性,我希望有这样的签名:function(newValue, propertyName)(可能是旧值... )。

下面的代码摘录显示我试图在该属性周围进行关闭,但它仍然会在扫描完最后一个属性时出现。

如何找出更改了哪个属性?

this.Data = ko.mapping.fromJS(dataFromServer);

...

ScrollDataItem.prototype.GetInformedOnChange = function () {
    var self = this;
    for(var prop in this.Data) {
        if(self.Data.hasOwnProperty(prop) && prop != "__ko_mapping__") {
            var closureProp = prop;
            self.Data[prop].subscribe(function (newValue) {
                alert("New value is: " + newValue);
                alert("Property that called: " + closureProp);
            });
        }
    }
};

1 个答案:

答案 0 :(得分:1)

您看到这个的原因是因为提升(http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-hoisting-explained/)。您声明的closureProp变量的作用域是GetInformedOnChange函数。 javascript中的变量始终作用于函数,而不是forwhile循环。

让我们来看看你所看到的。

假设this.Data中有2个属性:FirstName和LastName。第一次通过for(var prop in this.Data)循环时,prop是FirstName,因此为closureProp分配了名字。订阅已设置,但closesProp尚未用于任何事情,因为您订阅的内容尚未触发。

第二次进行循环时,closesProp(同一个变量 - 未创建新变量 - 请参阅上面的提升链接)被分配给LastName,然后设置了LastName的订阅。

然后,假设触发了FirstName订阅,则会调用您的匿名函数来执行警报。它使用closureProp,它被分配给LastName。

您可以通过添加额外的范围层来解决此问题,即额外的功能。方法如下:

创建一个新函数来处理订阅,提供额外的范围层:

function subscribeWithName(propName, observable) {
    var closureProp = propName;
    observable.subscribe(function(newValue) {
        alert("New value is: " + newValue);
        alert("Property that called: " + closureProp);
    });
}

调用此函数设置订阅:

for(var prop in this.Data) {
    if(self.Data.hasOwnProperty(prop) && prop != "__ko_mapping__") {
        subscribeWithName(prop, self.Data[prop]);            
    }
}

这是一个小提琴:http://jsfiddle.net/tlarson/PfaD7/