javascript KnockoutJS 使用相同的回调操作订阅多个 observable

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9278497/
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-26 06:08:54  来源:igfitidea点击:

KnockoutJS subscribe to multiple observables with same callback action

javascriptknockout.js

提问by Joel

I've got a model class in KnockoutJS which has multiple values that I'd like to subscribe to. Each subscription will perform the same task, like so:

我在 KnockoutJS 中有一个模型类,它有多个我想订阅的值。每个订阅都将执行相同的任务,如下所示:

function CaseAssignmentZipCode(zipCode, userId, isNew) {
  var self = this;
  self.zipCode = ko.observable(zipCode);
  self.userId = ko.observable(userId);
  self.isNew = isNew;
  self.isUpdated = false;

  self.zipCode.subscribe(function () { self.isUpdated = true; });
  self.userId.subscribe(function () { self.isUpdated = true; });
}

Is there a way to combine these two calls to subscribe, so that I can use one subscription to 'watch' both values?

有没有办法将这两个调用结合起来进行订阅,以便我可以使用一个订阅来“观看”这两个值?

回答by RP Niemeyer

You can use a computed observable for this purpose. You just need to make sure that you access the value of each observable in the read function. Would be something like:

为此,您可以使用计算出的 observable。您只需要确保在 read 函数中访问每个 observable 的值。会是这样的:

ko.computed(function() {
   self.zipCode();
   self.userId();
   self.isUpdated = true;
});

So, you get dependencies on the two observables and set your flag.

因此,您获得了对两个 observable 的依赖并设置了您的标志。

Also, if you are looking for something like a "dirty" flag, then you might consider something like: http://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html. The idea is that you use a computed observable that calls ko.toJS() on an object to unwrap all of its observables.

此外,如果您正在寻找类似“脏”标志的东西,那么您可能会考虑以下内容:http: //www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html。这个想法是你使用一个计算的 observable,它在一个对象上调用 ko.toJS() 来解包它的所有 observable。

回答by Sergio Tulentsev

Do you not want to duplicate handler function's body? Extract it to a variable.

您不想复制处理程序函数的主体吗?将其提取为变量。

function CaseAssignmentZipCode(zipCode, userId, isNew) {
  var self = this;
  self.zipCode = ko.observable(zipCode);
  self.userId = ko.observable(userId);
  self.isNew = isNew;
  self.isUpdated = false;

  var handler = function () { self.isUpdated = true; };

  self.zipCode.subscribe(handler);
  self.userId.subscribe(handler);
}

回答by wrschneider

Improving upon refactoring the function body into a variable, by turning the list of dependencies to track into a loop:

通过将要跟踪的依赖项列表转换为循环来改进将函数体重构为变量:

function CaseAssignmentZipCode(zipCode, userId, isNew) {
  var self = this;
  self.zipCode = ko.observable(zipCode);
  self.userId = ko.observable(userId);
  self.isNew = isNew;
  self.isUpdated = false;

  var handler = function () { self.isUpdated = true; };

  ko.utils.arrayForEach([self.zipCode, self.userId], function(obs) {
    obs.subscribe(handler);
  });
 } 

回答by cryss

You can create some kind of an extension for this purpose. Simple example:

您可以为此创建某种扩展。简单的例子:

function subscribeMany(callback, observables) {    
    for (var i = 0; i < observables.length; i++) {
        observables[i].subscribe(callback);
    }
}

Usage:

用法:

var name = ko.observable();
var email = ko.observable();

var callback = function(value) {
    console.log(value);
};

subscribeMany(callback, [name, email]);

name('test 1')
email('test 2')

回答by Asher Garland

Typescript version made for executing the same call back on any Observable in a list of Observables.

Typescript 版本用于在 Observable 列表中的任何 Observable 上执行相同的回调。

This solution works for the types:

此解决方案适用于以下类型:

  1. KnockoutObservableArray<KnockoutObservable<T>>
  2. KnockoutObservable<KnockoutObservable<T>[]>
  3. KnockoutObservable<T>[]
  1. KnockoutObservableArray<KnockoutObservable<T>>
  2. KnockoutObservable<KnockoutObservable<T>[]>
  3. KnockoutObservable<T>[]

Benefits of this approach:

这种方法的好处:

  1. If an Observable gets added to your KnockoutObservableArraythen the change will be detected and the subscribe function will be added to that Observable as well.
  2. The same solution can be used for many different types and the types are handled for you.

    function subscribeMany<T>(
        observables: KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> | KnockoutObservable<T>[],
        callback: (v: T) => void
        ): KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> | KnockoutObservable<T>[] {
    
        function _subscribeMany<T>(
            observables: KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> | KnockoutObservable<T>[],
            callback: (v: T) => void): void {
    
            if (_isObservableArray<T>(observables)) {
                _subcribeAndRun(observables, (array) => {
                    array.forEach((observable) => {
                        observable.subscribe(callback);
                    });
                });
            }
            else {
                ko.unwrap(observables).forEach((observable) => {
                    observable.subscribe(callback);
                });
            }
        }
    
        function _isObservableArray<T>(observables: KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> | KnockoutObservable<T>[]): observables is KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> {
            return "subscribe" in observables;
        }
    
        function _subcribeAndRun<T>(o: KnockoutObservable<T>, callback: (v: T) => void): KnockoutObservable<T> {
            o.subscribe(callback);
            callback(o());
    
            return o;
        }
    
        _subscribeMany<T>(observables, callback);
        return observables;
    }
    
  1. 如果一个 Observable 被添加到你的 Observable 中,KnockoutObservableArray那么将检测到更改,并且订阅功能也将添加到该 Observable 中。
  2. 相同的解决方案可用于许多不同的类型,并且为您处理这些类型。

    function subscribeMany<T>(
        observables: KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> | KnockoutObservable<T>[],
        callback: (v: T) => void
        ): KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> | KnockoutObservable<T>[] {
    
        function _subscribeMany<T>(
            observables: KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> | KnockoutObservable<T>[],
            callback: (v: T) => void): void {
    
            if (_isObservableArray<T>(observables)) {
                _subcribeAndRun(observables, (array) => {
                    array.forEach((observable) => {
                        observable.subscribe(callback);
                    });
                });
            }
            else {
                ko.unwrap(observables).forEach((observable) => {
                    observable.subscribe(callback);
                });
            }
        }
    
        function _isObservableArray<T>(observables: KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> | KnockoutObservable<T>[]): observables is KnockoutObservableArray<KnockoutObservable<T>> | KnockoutObservable<KnockoutObservable<T>[]> {
            return "subscribe" in observables;
        }
    
        function _subcribeAndRun<T>(o: KnockoutObservable<T>, callback: (v: T) => void): KnockoutObservable<T> {
            o.subscribe(callback);
            callback(o());
    
            return o;
        }
    
        _subscribeMany<T>(observables, callback);
        return observables;
    }