2015-07-11 59 views
3

我很难从Angular服务公开属性。在下面的例子中,我公开了authService中的两个属性:isAuthenticateduser。但是,当isAuthenticated发生变化时,HomeController不会收到。有人能帮助我了解我哪里出错了吗?AngularJS - 如何公开服务属性

(function() { 
    'use strict'; 

    // Define the 'app' module 
    angular.module('app', []); 

    // Use the 'app' module 
    angular 
     .module('app') 
     .controller('LoginController', LoginController) 
     .controller('HomeController', HomeController) 
     .factory('authService', authService); 


    // ----- LoginController ----- 
    LoginController.$inject = ['authService']; 
    function LoginController(authService) { 

     var vm = this; 
     vm.username = null; 
     vm.password = null; 
     vm.login = login; 

     function login() { 
      authService.login(vm.username, vm.password); 
     } 
    } 


    // ----- HomeController ----- 
    HomeController.$inject = ['$scope', 'authService']; 
    function HomeController($scope, authService) { 

     var vm = this; 
     vm.user = null; 

     $scope.$watch(
      function() { return authService.isAuthenticated; }, 
      function() { 
       console.log('HomeController: isAuthenticated changed'); 
       vm.user = authService.user; 
      } 
     ); 
    } 


    // ----- authService ----- 
    function authService() { 

     var isAuthenticated = false; 
     var user = { username: 'jdoe', location: 'Dreamland' }; 

     var service = { 
      login: login, 
      isAuthenticated: isAuthenticated, 
      user: user 
     }; 

     return service; 

     function login(username, password) { 

      user = { 
       username: username, 
       location: 'Boston' 
      }; 

      isAuthenticated = true; 
      console.log('authService: isAuthenticated changed'); 
     } 
    } 

})(); 

下面是index.html文件:

<!DOCTYPE html> 
<html data-ng-app="app" ng-strict-di> 
<head> 
    <meta charset="utf-8"> 
    <title>AngularJS Minimal Template</title> 
    <link rel="stylesheet" href="app.css"> 
</head> 

<body> 
    <div ng-controller="LoginController as vm"> 
     <form name="loginForm" ng-submit="vm.login()"> 
      <label>Username: </label> 
      <input type="text" name="username" ng-model="vm.username"> 

      <label>Password: </label> 
      <input type="password" name="password" ng-model="vm.password"> 

      <button type="submit">Login</button> 
     </form> 
    </div> 

    <div ng-controller="HomeController as vm"> 
     <h1>{{vm.user.username}}</h1> 
     <h2>{{vm.user.location}}</h2> 
    </div> 

    <!-- JavaScript at the bottom for fast page loading --> 
    <script src="lib/angular.js"></script> 
    <script src="app.js"></script> 
</body> 
</html> 
+0

service.isAuthenticated = true,而不是那个。布尔值是按值传递,而不是引用。 – YOU

+0

而不是让isAuthenticated一个局部变量我只需要isAuthenticated:当您初始化服务对象时为false。然后在您的登录功能中,您可以将service.isAuthenicated设置为true,并在您的服务中返回该单例对象。在JS中,函数被悬挂到顶端,这意味着var isAuthenticated = false在代码被解释时出现在登录函数之后。这可能会导致你的问题。 –

回答

4

当你这样做:

var service = { 
    login: login, 
    isAuthenticated: isAuthenticated, 
    user: user 
}; 

你正在创建的副本loginisAuthenticateduser(虽然user是同一对象的引用)。

然后,当你这样做:

function login(username, password) { 

    user = { 
     username: username, 
     location: 'Boston' 
    }; 

    isAuthenticated = true; 
    console.log('authService: isAuthenticated changed'); 
} 

您重新分配当地user变量到一个新的对象和当地isAuthenticated变量true。您的service对象仍然指旧的这些变量的值。

最直接的方式来解决这个问题是直接分配给您的服务变量:

function login(username, password) { 

    service.user = { 
     username: username, 
     location: 'Boston' 
    }; 

    service.isAuthenticated = true; 
    console.log('authService: isAuthenticated changed'); 
} 

这样,服务变量将被更新,并应在任何地方反映该服务被使用。在这种情况下,你不再需要局部变量 - 服务对象已经容纳了它们。使用私有的未暴露变量的局部变量。

+1

工程就像一个魅力!谢谢! – Naresh

+0

_“您正在创建登录,isAuthenticated和用户的副本” - - 并非如此。这些只是任务。你不能复制'false'。 – zeroflagL

+0

@zeroflagL是的。例如,我的意思是,'service.isAuthenticated'成为'isAuthenticated'的副本 - 虽然两者与'false'相同,但'service.isAuthenticated'是'isAuthenticated'的副本,因为'isAuthenticated'可以更改而不会影响'service.isAuthenticated'。 – Agop

0

而不是做这个

var service = { 
      login: login, 
      isAuthenticated: isAuthenticated, 
      user: user 
     }; 

尝试这样做

var service = { 
      login: login, 
      isAuthenticated: function() { return isAuthenticated; }, 
      user: function() { return user; } 
     }; 

然后,你需要把它叫为功能不作为价值。这将检查isAuthenticated价值,并在每次拨打电话service.isAuthenticated()时将其返回。你应该这样做user。您应该致电service.user()

+0

谢谢,@Mindastic。这解决了一个问题。 $ watch现在正在工作,并在'isAuthenticated'发生变化时被调用。但是,'authService.user'不会获取用户的新值。它仍然有初始值(jdoe/Dreamland)。我尝试将var服务更改为'user:function(){return user; }',但这没有帮助。 – Naresh

+0

对于用户,你应该做几乎相同。检查我更新的答案。 – Mindastic

+0

不幸的是不起作用。我编辑了我之前的评论,说可能你没有阅读编辑过的版本。无论如何,请参阅@ Agop的答案,这是有效的。 – Naresh