【问题标题】:AngularJs: How to access global variables outside of controller? [duplicate]AngularJs:如何访问控制器外部的全局变量? [复制]
【发布时间】:2013-10-08 21:10:52
【问题描述】:

我正在尝试通过普通函数访问全局变量,可以吗?

我已经使用 $rootScope 设置了一些 var,我正在尝试通过回调函数访问它。 这个回调是从控制器调用的。我不想在那个回调中传递$rootScope

有什么方法可以访问$rootScope.var 吗?

如果可能,我愿意使用服务。

请提出建议。

谢谢

我正在尝试访问 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 fn 下将 isFBLoggedin 显示为 true,但它没有反映在视图中

我正在打印{{isFBLoggedin}},但 ts 显示为假

终于成功了。

我遵循了@dluz 的解决方案。

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

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    请不要使用 $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 exists, but it can be used for evil

    Angular 中的作用域形成一个层次结构,原型继承自树顶部的根作用域。通常这可以忽略,因为大多数视图都有自己的控制器,因此也有自己的范围。

    有时,您想让某些数据对整个应用程序具有全局性。对于这些,您可以像任何其他范围一样注入 $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>
    

    【讨论】:

    • 没错,但是我可以直接从正常功能访问该服务吗?
    • 您的“正常功能”在哪里定义?!?它将在directivecontroller 内,对吧?!?所以答案是肯定的,您只需将该服务添加为指令或控制器的依赖项。如果您的正常功能是在其他地方定义的,那就是代码设计问题,您需要检查您的逻辑。
    • “正常功能”是什么意思?任何 Angular 范围之外的函数?听起来您有代码设计问题...
    • @Scalpweb 请看我的编辑
    • 感谢@dluz,它的服务为我工作,但我正在考虑问题。在我看来,即 FBLoggedin 没有更新
    【解决方案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 */
        }
    }
    

    【讨论】:

    • 谢谢,但我需要该控制器之外的回调函数中的 var
    • 为什么不能在控制器中定义这个回调?
    • 因为这是一个实用函数,也可以通过其他一些函数访问
    • 所以也许你应该在 rootScope 中定义这个函数?
    • 你能告诉我一些例子,我们可以把这些函数放在 rootScope 中并从任何地方访问它们吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多