44

有没有办法在可观察的值变化时忽略订阅者。我想更改 observable 的值,但不为带有 knockout.js 的订阅者执行它

4

4 回答 4

82

通常这是不可能的或不可取的,因为它可能会使依赖链中的事物不同步。使用限制扩展器通常是限制依赖项接收的通知数量的好方法。

但是,如果您真的想这样做,那么一种选择是覆盖notifySubscribersobservable 上的函数并让它检查一个标志。

这是一个将此功能添加到可观察对象的扩展:

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");
于 2013-08-01T02:39:40.433 回答
17

一个更简单的方法:

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");

需谨慎使用。我们正在处理一个可观察的对象,所以如果你没有通知你的订阅者,就会发生不好的事情。

于 2016-06-22T07:26:24.020 回答
8

当需要忽略所有订阅者时,我喜欢@RP Niemeyer提供的解决方案。但是,就我而言,我在 Select 控件上有一个带有 2 路绑定的 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
于 2015-10-30T15:00:16.100 回答
1

我来这个问题是因为我正在构建一个分页数据网格。只显示了 10 行,每行都有一个复选框。表头有一个(取消)全选复选框。

在负载测试期间,我们发现单击全选复选框会导致一次更新 1000 个 observables。这花费的时间太长了。

即使只有 10 个 observables 绑定到 HTML,KO 似乎更新了 html 1000 次。

如果有人出于同样的原因发现这个问题,我建议查看延迟更新。延迟更新队列通知订阅者,它会在您的“线程”完成后通知您的订阅者。延迟更新可以为每个 observable 或整个应用程序配置。

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

于 2017-04-06T07:35:16.440 回答