更改可观察但不通知knockout.js中的订阅者

时间:2013-08-01 00:10:20

标签: javascript events knockout.js

有没有办法忽略订阅者对可观察值的变化。我想改变一个observable的值,但不是为具有knockout.js的订阅者执行它

4 个答案:

答案 0 :(得分:82)

通常这是不可能或不可取的,因为它可能会使依赖链中的内容不同步。使用节流扩展器通常是限制依赖关系接收的通知量的好方法。

但是,如果你真的想这样做,那么一个选项就是覆盖一个observable上的notifySubscribers函数并让它检查一个标志。

这是一个将此功能添加到observable的扩展:

ko.observable.fn.withPausing = function() {
    this.notifySubscribers = function() {
       if (!this.pauseNotifications) {
          ko.subscribable.fn.notifySubscribers.apply(this, arguments);
       }
    };

    this.sneakyUpdate = function(newValue) {
        this.pauseNotifications = true;
        this(newValue);
        this.pauseNotifications = false;
    };

    return this;
};

您可以将其添加到可观察的内容中:

this.name = ko.observable("Bob").withPausing();

然后你会在没有通知的情况下更新它:

this.name.sneakyUpdate("Ted");

答案 1 :(得分:14)

更简单的方法:

ko.observable.fn.silentUpdate = function(value) {
    this.notifySubscribers = function() {};
    this(value);
    this.notifySubscribers = function() {
        ko.subscribable.fn.notifySubscribers.apply(this, arguments);
    };
};

按如下方式使用:

this.status = ko.observable("Happily Married");
this.walkIntoBar();
this.status.silentUpdate("Single");
this.walkOutOfBar(); // careful with exceptions
this.status.silentUpdate("Happily Married");

谨慎使用。我们正在处理一个可观察的对象,如果您未通知订阅者,可能会发生不好的事情。

答案 2 :(得分:6)

当所有订阅者都需要被忽略时,我喜欢 @RP Niemeyer 提供的解决方案。但是,对于我的情况,我在Select控件上有一个带有双向绑定的observable。使用 @RP Niemeyer 时,Select控件未更新。所以,我真的需要一种方法来关闭特定的观察者,而不是所有观察者。以下是此案例的一般化解决方案。

为“安静”添加扩展程序'订阅和安静'写入。

ko.observable.fn.ignorePokeSubscribe = function (callback, thisValue, event){
    var self = this;
    this.subscribe(function(newValue) {
        if (!self.paused)
            callback(newValue);
    }, thisValue, event);
    return this;
};
ko.observable.fn.poke = function (newValue) {
    this.paused = true;
    var result = this(newValue);
    this.paused = undefined;
    return result;
};

您可以订阅observable,如:

this.name = ko.observable("Bob");
this.name.ignorePokeSubscribe(function(newValue) { /* handler */ }));

然后您可以通过执行以下操作更新它而无需特定通知:

this.name.poke("Ted");   // standard subscribers still get notified

答案 3 :(得分:1)

我遇到了这个问题,因为我正在构建一个分页数据网格。仅显示了10行,每行都有一个复选框。表头有一个(de)select all复选框。

在加载测试期间,我们发现单击全选复选框导致一次更新1000个可观察对象。这花了太长时间。

似乎KO将html更新了1000次,尽管只有10个observable绑定到了HTML。

如果有人出于同样的原因发现了这个问题,我建议您查看延期更新。延期更新排队通知订阅者,它会在您的'线程后通知您的订阅者。已经完成了。延迟更新可根据可观察或整个应用程序进行配置。

http://knockoutjs.com/documentation/deferred-updates.html