我可以在每个控制器中使用角度功能吗?


191

如果我有一个实用函数foo,我希望能够从我ng-app声明的任何地方调用。是否可以通过模块设置使其全局访问,还是需要将其添加到每个控制器的作用域中?


我对此不是100%的确定,但是有机会您也可以在模块上这样定义它:module.value('myFunc', function(a){return a;});然后在控制器中按名称注入它。(如果要避免提供服务)
user2173353 2014年

这意味着我必须将其手动添加到每个控制器中。$ rootScope是我将近2年前想做的事情的方法=)
路德维希·马格努森

好。:)我只使用带有隔离范围的指令而不是使用普通控制器,并且无论如何我都必须注入所有内容。我喜欢它提供的模块化代码样式。同样,您不必以任何方式弄乱父级作用域,也不必为范围变量的来源进行大量搜索。:)
user2173353

Answers:


290

基本上,您有两个选择,要么将其定义为服务,要么将其放在根范围内。我建议您使用它来提供服务,以避免污染根范围。您创建一个服务,并使其在控制器中可用,如下所示:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.factory('myService', function() {
        return {
            foo: function() {
                alert("I'm foo!");
            }
        };
    });

    myApp.controller('MainCtrl', ['$scope', 'myService', function($scope, myService) {
        $scope.callFoo = function() {
            myService.foo();
        }
    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="callFoo()">Call foo</button>
</body>
</html>

如果这不是您的选择,则可以将其添加到根范围,如下所示:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.run(function($rootScope) {
        $rootScope.globalFoo = function() {
            alert("I'm global foo!");
        };
    });

    myApp.controller('MainCtrl', ['$scope', function($scope){

    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="globalFoo()">Call global foo</button>
</body>
</html>

这样,您所有的模板都可以调用,globalFoo()而不必将其从控制器传递到模板。


5
在第一个解决方案中,如果有大量foo()功能该怎么办?$scope.callFoo()为他们每个人做一个包装是太多的工作。如何库的所有功能“附加”到作用域中,以便可以在模板中使用它?我有一个很大的单位转换库,我希望它可以在我的模板上使用。
AlexStack

3
我的问题也是如此。我尝试了一下,它起作用了:您可以通过说“附加”它,$scope.callFoo = myService.foo;而不是在要使用它的每个位置创建一个新包装。
钳工人

1
感谢您的帮助,我想知道如何在整个应用程序中使用更改语言功能,而$ rootScope可以完成这项工作。我想将翻译模块与应用程序分开,这样我也可以将其插入其他应用程序。
Paulo Pedroso,2015年

我建议在这种情况下使用角度值而不是工厂,除非您计划在服务中具有多个功能。如果只是一个功能,请将其设为值。
Nicholas Blasgen

我收到错误消息:[$ injector:unpr]
Mark Thien

53

我猜你也可以把它们结合起来:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
        var myApp = angular.module('myApp', []);

        myApp.factory('myService', function() {
            return {
                foo: function() {
                    alert("I'm foo!");
                }
            };
        });

        myApp.run(function($rootScope, myService) {
            $rootScope.appData = myService;
        });

        myApp.controller('MainCtrl', ['$scope', function($scope){

        }]);

    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="appData.foo()">Call foo</button>
</body>
</html>

7
我认为这应该是正确的答案,以@Praym的答案为依据。在10个不同的控制器中指定服务依赖关系没有意义。
jvannistelrooy 2014年

服务可以包含可以在其中添加CRUD属性/变量的方法/功能$rootScope吗?
jezmck

44

尽管第一种方法被提倡为“类似角度”方法,但我认为这会增加开销。

考虑是否要在10个不同的控制器中使用此myservice.foo函数。我将必须在所有十个实例中指定此“ myService”依赖项,然后指定$ scope.callFoo范围属性。这仅仅是重复,并且某种程度上违反了DRY原理。

而如果我使用$ rootScope方法,则只指定一次此全局函数gobalFoo,它将在以后的所有控制器中使用,无论有多少个控制器。


5
控制器在“记录”中获得全局服务调用的地方可能会有一些价值。如果您将一个控制器拖到另一个应用程序中,则不清楚该全局函数的来源。不过,我听到您的论点。
马修·佩恩

仅当您需要从视图中调用它时,才需要将它放在示波器上。在控制器中,您可以直接从服务中调用它。
mcv 2015年

10
这不是评论,而是答案
Elliott 2015年

$ rootScope变量在页面刷新时始终为null,在这种情况下,您将不会获得该函数。这就是为什么将服务注入并在应用程序中使用其引用的原因。
Ehsan Hafeez

4

AngularJs有“ 服务 ”和“ 工厂 ”只是像yours.These问题曾经有过一些全球控制器,指令,其他服务或任何其他angularjs组件之间的 ..你可以定义函数,存储数据时,请计算功能或任何你想要在服务内部并将其在AngularJs组件中用作Global .like

angular.module('MyModule', [...])
  .service('MyService', ['$http', function($http){
    return {
       users: [...],
       getUserFriends: function(userId){
          return $http({
            method: 'GET',
            url: '/api/user/friends/' + userId
          });
       }
       ....
    }
  }])

如果您需要更多

查找有关我们为什么需要AngularJs服务和工厂的更多信息


0

我是Angular的新手,但是我发现有用的方法(非常简单)是我创建了一个全局脚本,该脚本先加载到页面上,然后再使用需要在所有页面上访问的全局变量的本地变量。在该脚本中,我创建了一个名为“ globalFunctions”的对象,并添加了需要全局访问的函数作为属性。例如globalFunctions.foo = myFunc();。然后,在每个本地脚本中,我编写了代码,$scope.globalFunctions = globalFunctions;并且可以立即访问添加到全局脚本中的globalFunctions对象的任何函数。

这是一个变通办法,我不确定它是否对您有帮助,但由于我有很多功能,因此将其全部添加到每个页面上确实很痛苦。


1
我很好奇为什么不赞成投票?我是新手,想从专业人士那里了解一下。
Izzy

对我来说似乎是一个可行的解决方案。为了确保您的作用域被充分隔离,我提倡的唯一一件事就是创建一个全局根Javascript实用程序类,并将您的实用程序方法挂在该类之外,以免您意外地踩到了其他函数名。 Angular注入了浩瀚的事物。
JE卡特二世

需要注意的一件事,也许是为什么要这样做,您只能在模板中使用这些函数,而不能在.ts模块中使用这些函数,因为函数调用在编译时无法解析。这就是这样做的原因。但是,如果只想向模板添加装饰器等,则全局实用程序文件既简单又好。
JE卡特二世
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.