AngularJs:如何在控制器之外访问全局变量?

6

我想通过一个普通函数访问一个全局变量,这种做法可行吗?

我使用了$rootScope设置了一些变量,并试图通过一个回调函数来访问它。这个回调函数是从控制器调用的。我不想在回调函数中传递$rootScope。

有办法可以访问 $rootScope.var 吗?

如果可以,我可以使用 service。

请给出建议。

谢谢。

我尝试以下方式访问rootScope:

    function fbLandingCtrl($scope, $rootScope) {
    $rootScope.isFBLoggedin = false;
    $scope.login = function() {
       console.log( $rootScope.isFBLoggedin);
       fbHelper.login(getUserInfo);
      };

      function getUserInfo(){
          fbHelper.getUserInfo(updateStatus);
      }
      function updateStatus(userInfo){
          $rootScope.isFBLoggedin = true;
          console.log( $rootScope.isFBLoggedin);
      }
  }

我的服务包括:

    myapp.factory('FBService', [ '$rootScope', function ($rootScope) {
    $rootScope.isFBLoggedin = false; // global variable
    $rootScope.userName = null;
    $rootScope.userEmail = null;

    return {

        getStatus: function() {
            return $rootScope.isFBLoggedin;
        },
        setStatus: function(status) {
            console.log("Status:"+status);
            return $rootScope.isFBLoggedin = status;
        }
       };
}]);

在updateStatus函数下,它显示isFBLoggedin为true,但在视图中没有反映出来。

我打印了{{isFBLoggedin}},但是它显示为false。

最终它正常工作了。

我按照@dluz的解决方案进行操作。

我还使用了$rootScope.$apply(function() {}})来渲染视图。

2个回答

5
请不要使用$rootScope来定义任何函数,这是非常糟糕的做法。请记住,$rootScope毕竟是全局变量。
您可以通过以下方式使用服务获取$rootScope:
<!doctype html>
 <html lang="en" ng-app="myApp">
  <head>
<meta charset="UTF-8">
<title>Document</title>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>

  <script>

     var myApp = angular.module('myApp', []);

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

       console.log(myService.getData());
    
}])

        myApp.factory('myService', [ '$rootScope', function ($rootScope) {
    
       return {
        
        getData: function() {
            return $rootScope;
        }
       };
      }])


    </script>

  </head>
  <body ng-controller="myAppCtrl">

   </body>
   </html>

$rootScope 存在,但它可能被用于恶意目的

Angular 中的 Scopes 组成一个层次结构,原型继承自树顶上的根 scope。通常可以忽略这一点,因为大多数视图都有其自己的控制器和作用域。

偶尔会有一些数据需要成为整个应用程序的全局数据。对于这些数据,您可以注入 $rootScope 并像任何其他作用域一样设置值。由于作用域从根作用域继承,因此这些值将对指令(如 ng-show)附加的表达式可用,就像本地 $scope 上的值一样。

当然,全局状态很糟糕,应该谨慎使用 $rootScope,就像您在任何语言中使用全局变量一样。特别是,不要将其用于代码,只能用于数据。如果您想在 $rootScope 上放置一个函数,则几乎总是更好的将其放在可以在需要时注入的服务中,并且更容易测试。

相反地,请勿创建其唯一目的是存储和返回数据片段的服务。

更新的答案

A_J,我不确定您的应用程序场景。为了给出更好的答案,我需要查看更多代码,但请查看下面的代码。也许它可以给您一些想法,如何设计您的代码以在 service 内部访问 $rootScope

按下“登录”按钮并查看您的控制台。这里是可工作的示例 (http://jsbin.com/olOyaHa/1/)

 <!doctype html>
 <html lang="en" ng-app="myApp">
    <head>
 <meta charset="UTF-8">
 <title>Document</title>
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>

 <script>

     var myApp = angular.module('myApp', []);

     myApp.controller('fbLandingCtrl', ['$scope', '$rootScope', 'loginService', function ($scope, $rootScope, loginService) {

    $rootScope.isFBLoggedin = false;
    
    $scope.login = function() {
       console.log('Current login status', $rootScope.isFBLoggedin);

       console.log(loginService.getUserInfo());

       loginService.login(loginService.getUserInfo());

       loginService.updateStatus();
      };

    
     }]);


     myApp.factory('loginService', [ '$rootScope', function ($rootScope) {
    
    return {
        
        login: function() {
            console.log('now I am logged in!');
            return $rootScope.isFBLoggedin = true;
        },

        getUserInfo: function() {
            return {
                username: 'xmen',
                role: 'admin',
                logged: 'false'
            };
        },
        
        updateStatus: function(userInfo){
            $rootScope.isFBLoggedin = true;
            console.log('Current login status', $rootScope.isFBLoggedin);
        }
        };
     }])


    </script>

 </head>
 <body ng-controller="fbLandingCtrl">
    <button ng-click="login()">Log Me In</button>
 </body>
 </html>

确切地说,但我能直接从普通函数访问该服务吗? - A_J
1
你的“正常函数”定义在哪里?!它会在指令或控制器内部定义,对吗?!所以答案是肯定的,你只需要将该服务作为指令或控制器的依赖添加即可。如果你的正常函数定义在其他地方,那么这是一个代码设计问题,你需要重新审查你的逻辑。 - Denison Luz
你所说的“普通函数”是什么意思?指的是在任何Angular作用域之外的函数吗?听起来像是你的代码设计存在问题... - Scalpweb
感谢@dluz,它的服务对我有用,但是我在视图中遇到了问题。即FBLoggedin在我的视图中没有被更新。 - A_J
感谢@dluz和@Scalpweb快速回复。现在它对我有用了,我必须使用$rootScope.$apply(function() {}}) - A_J

2

如果您将$rootScope添加为控制器引用,则可以在控制器内访问$rootScope.var:

function MyCtrl($scope, $rootScope, $routeParams /*, ... */)
{
  /* Controller code and callback code here */
}

只要您的回调函数在控制器中定义,它就可以正常工作。
编辑:在我们的讨论之后,这是如何在rootScope中定义一个函数:
yourApp.run($rootScope/*, ResourceProvider ... */) {
    $rootScope.yourFunction= function () {
        /* The code of you functions */
    }
}

谢谢,但我需要在回调函数中使用那个变量,在控制器之外。 - A_J
为什么不能在控制器内定义此回调函数? - Scalpweb
因为这是一个实用函数,其他一些函数也可以访问。 - A_J
所以也许你应该在rootScope内定义这个函数? - Scalpweb
你能给我展示一些例子吗,我们可以把这些函数放在rootScope中并从任何地方访问它们吗? - A_J

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接