【问题标题】:Importing multiple AngularJS module's factories导入多个 AngularJS 模块的工厂
【发布时间】:2014-08-19 00:26:20
【问题描述】:

我想知道是否有一种方法可以将我在 AngularJS 模块中定义的所有工厂导入控制器,而不必将它们全部列出。假设我有一个名为 foo.js 的文件,其中包含:

angular.module("Foo", [])
.factory("Bar1", function() {...})
.factory("Bar2", function() {...})
.factory("Bar3", function() {...})
.factory("Bar4", function() {...});

现在,在我的 controller.js 文件中,我有:

angular.module("myApp.controllers", ["Foo"]).
controller("MainCtrl", ["Bar1", "Bar2", "Bar3", "Bar4", function(bar1, bar2, bar3, bar4) {
    //do stuff with the various bars
}]);

我只是想知道控制器是否有任何优雅的方式,因为它已经导入模块Foo,以查看其所有工厂(或提供者,或服务,或事实上的指令)。

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    是的,这是可能的。

    您可以动态加载模块并检查其_invokeQueue 字段(请参阅https://stackoverflow.com/a/19412176/646543),以检索模块中定义的所有工厂/控制器/等的名称。

    然后您可以使用$injector 服务来实际检索工厂。

    为了演示,我创建了一个快速的演示证明。您应该能够直接将IntrospectModule 工厂复制并粘贴到您的应用中以获取此功能。

    // Creating some test services
    angular.module('test-services', [])
        .factory('Bar1', function() {
            return { 'stuff': function() { return 'calling bar1' } };
        })
        .factory('Bar2', function() {
            return { 'stuff': function() { return 'calling bar2' } };
        });
    
    angular.module('myapp', ['test-services'])
        .factory('IntrospectModule', function($injector) {
            // This factory will dynamically return all services/controllers/directives/etc
            // given the module name.
    
            return function (moduleName) {
                var out = {};
                angular.module(moduleName)._invokeQueue.forEach(function(item) {
                    var name = item[2][0];
                    out[name] = $injector.get(name);
                });
                return out;
            };
        })
        .controller('MainCtrl', function($scope, IntrospectModule) {
            // And now I'm using it
            var testServices = IntrospectModule('test-services');
            $scope.test = testServices.Bar1.stuff();
        });
    

    这是上述工作的plnkr


    或者,如果感觉太老套,您可以尝试创建一个“复合”工厂:

    angular.module("test-services", [])
        .factory("Bar1", function() {...})
        .factory("Bar2", function() {...})
        .factory("Bar3", function() {...})
        .factory("Bar4", function() {...})
        .factory("EveryBar", ["Bar1", "Bar2", "Bar3", "Bar4", 
            function(bar1, bar2, bar3, bar4) {
                return {
                    'bar1': bar1, 
                    'bar2': bar2,
                    'bar3': bar3,
                    'bar4': bar4
                };
            }]);
    

    然后,在您的控制器中,执行以下操作:

    angular.module("myApp.controllers", ["test-services"]).
    controller("MainCtrl", ["EveryBar", function(everyBar) {
        everyBar.bar1.stuff();
    }]);
    

    显然,这种方法的缺点是在设置服务时会导致大量冗余——我们仍然手动列出所有内容。

    但是,如果您需要在多个不同的控制器中多次使用相同的服务,那么创建复合服务至少可以让您避免在每个控制器中列出一堆参数。

    它也比第一个解决方案更明确,并且允许您准确地枚举您想要的服务,而不是在 Angular 的内部乱搞,并允许您扩展服务、添加帮助器/包装器函数等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-19
      • 1970-01-01
      • 2014-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多