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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17983118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 10:19:39  来源:igfitidea点击:

Change observable but don't notify subscribers in knockout.js

javascripteventsknockout.js

提问by Mike Flynn

Is there a way to ignore subscribers on a value change of the observable. Id like to change a value of an observable, but not execute it for the subscribers with knockout.js

有没有办法在 observable 的值变化时忽略订阅者。我想更改 observable 的值,但不为使用 Knockout.js 的订阅者执行它

回答by RP Niemeyer

Normally this is not possible or advisable, as it potentially allows things to get out of sync in the dependency chains. Using the throttle extender is generally a good way to limit the amount of notifications that dependencies are receiving.

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

However, if you really want to do this, then one option would be to overwrite the notifySubscribersfunction on an observable and have it check a flag.

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

Here is an extensions that adds this functionality to an observable:

这是一个将此功能添加到 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;
};

You would add this to an observable like:

您可以将其添加到一个 observable 中,例如:

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

Then you would update it without notifications by doing:

然后您可以通过执行以下操作在没有通知的情况下更新它:

this.name.sneakyUpdate("Ted");

回答by Steven de Salas

An even simpler approach:

一个更简单的方法:

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

Use it as follows:

使用方法如下:

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

To be used with caution. We are dealing with an observable object so bad things can happen if you fail to notify your subscribers.

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

回答by raider33

I like the solution provided by @RP Niemeyerwhen all subscribers need to be ignored. However, for my case, I have an observable with 2-way bindings on a Select control. When using @RP Niemeyer, the Select control isn't updated. So, I really needed a way to turn off specific observers, not all. Here is a generalized solution for this case.

当需要忽略所有订阅者时,我喜欢@RP Niemeyer提供的解决方案。但是,就我而言,我在 Select 控件上有一个带有 2 路绑定的 observable。使用@RP Niemeyer 时,不会更新 Select 控件。所以,我真的需要一种方法来关闭特定的观察者,而不是全部。这是针对这种情况的通用解决方案。

Add extensions methods for 'quiet' subscribe and 'quiet' writes.

为“安静”订阅和“安静”写入添加扩展方法。

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;
};

You would subscribe to observable like:

你会订阅 observable 像:

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

Then you would update it without specific notifications by doing:

然后您可以通过执行以下操作在没有特定通知的情况下更新它:

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

回答by Rob

I came to this question because I was building a paged datagrid. Only 10 rows were shown and each row has a checkbox. The table header had a (de)select all checkbox.

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

During load tests we discovered that clicking the select all checkbox resulted in updating 1000 observables at once. This took way too long.

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

It seemed that KO updated the html 1000 times even though only 10 observables were bound to HTML.

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

If anyone finds this question for the same reason, I would suggest looking into deferred updates. Deferred updates queue notifying subscribers, it notifies your subscribers after your 'thread' is done. Deferred updates is configurable per observable or for your whole application.

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

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

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