2

我需要一个时间戳来更新值。由于我不会在这里讨论的原因,它value是一个可写的计算,它指向一个valueInstance可观察的,所以它们基本上显示相同的数据。

如果我订阅了 observable,它会按预期工作,只有在 observable 发生变化时才会触发。如果我订阅了计算,它会立即触发,导致错误的时间戳,即使 observable 仍然未定义。这是怎么回事?

http://jsfiddle.net/bNXhm/

更新:看起来这只发生在计算有deferEvaluation: true

http://jsfiddle.net/bNXhm/1/

function VM(){
    var self = this;

    self.valueInstance = ko.observable();
    self.value = ko.computed({
        read: function () {
            return self.valueInstance();
        },
        write: function (value) {
            self.valueInstance(value);
        },
        deferEvaluation: true
    });

    self.timeStamp1 = ko.observable();
    self.value.subscribe(function (newValue) {
        self.timeStamp1(new Date());
    });

    self.timeStamp2 = ko.observable();
    self.valueInstance.subscribe(function (newValue) {
        self.timeStamp2(new Date());
    }); }
4

2 回答 2

1

当您deferEvalaution在有人请求其值之前不会评估计算的值。绑定时会发生这种情况。当它被评估时,它会通知任何订阅者。这可以解释为什么您的订阅会受到打击。

于 2013-07-25T14:30:12.670 回答
1

当你创建一个 observable 时,它​​将被评估,除非你将 deferEvaluation 设置为 true。当评估一个可观察的(或计算的)时,它总是通知他们订阅者。此时没有与之前的值进行比较(以便仅在值更改时通知)。

“无用的通知检查”是在 observable 的 setter 中进行的。

因此,在您的代码中,当您使用 deferEvaluation 为 false 时,会立即评估读取函数并通知订阅者。但此时没有订阅者。这就是为什么没有设置时间跨度的原因。

当您使用 deferEvaluation : true 时,评估过程是 applyBindings 函数中的延迟。此时您已经订阅了,这就是设置时间跨度的原因。

为了解决您的问题,我将创建一个变量来存储您何时应该开始记录更改。

function VM(){

    var self = this;
    self.logged  = false;


    self.valueInstance = ko.observable();
    self.value = ko.computed({
        read: function () {
            return self.valueInstance();
        },
        write: function (value) {
            self.valueInstance(value);
        },
        deferEvaluation: true
    });

    self.timeStamp1 = ko.observable();
    self.value.subscribe(function (newValue) {
        if(self.logged)
            self.timeStamp1(new Date());
    });

    self.timeStamp2 = ko.observable();
    self.valueInstance.subscribe(function (newValue) {
        if(self.logged)
             self.timeStamp2(new Date());
    });
}
var vm  = new VM();
ko.applyBindings(vm);
vm.logged = true;

我希望它有帮助

见小提琴

于 2013-07-25T15:39:45.120 回答