【问题标题】:AngularJS - How to expose service propertiesAngularJS - 如何公开服务属性
【发布时间】:2015-09-30 05:40:15
【问题描述】:

我很难从 Angular 服务中公开属性。在下面的示例中,我公开了authService 中的两个属性:isAuthenticateduser。但是,当isAuthenticated 更改时,HomeController 不会接收到它。有人可以帮助我了解我哪里出错了吗?

(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>

【问题讨论】:

  • service.isAuthenticated = true,而不是那个。 boolean 是按值传递,而不是引用。
  • 而不是将 isAuthenticated 设为局部变量,我只会在初始化服务对象时使用 isAuthenticated: false 。然后在您的登录功能中,您可以将 service.isAuthenicated 设置为 true 并在您的服务中返回该单例对象。在 JS 中,函数被提升到顶部,这意味着当您的代码被解释时,var isAuthenticated = false 出现在登录函数之后。这可能会导致您的问题。

标签: angularjs angularjs-service


【解决方案1】:

当你这样做时:

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');
}

您正在将 local user 变量重新分配给一个新对象,并将 local isAuthenticated 变量重新分配给 true。您的service 对象仍然引用这些变量的值。

解决此问题的最直接方法是直接分配给您的服务变量:

function login(username, password) {

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

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

这样,服务变量将被更新,并且应该反映在使用服务的任何地方。在这种情况下,您不再需要局部变量 - 服务对象已经包含它们。对私有的、未公开的变量使用局部变量。

【讨论】:

  • 像魅力一样工作!谢谢!
  • “您正在创建 login、isAuthenticated 和 user 的副本” - 并非如此。这些只是任务。你不能复制false
  • @zeroflagL 是的。我的意思是,例如,service.isAuthenticated 成为isAuthenticated 的副本——尽管两者都与false 相同,service.isAuthenticatedisAuthenticated 的副本,因为isAuthenticated 可以在不影响@987654339 的情况下更改@.
【解决方案2】:

而不是这样做

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()

【讨论】:

  • 谢谢,@Mindastic。这解决了一个问题。 $watch 现在可以工作了,只要isAuthenticated 发生变化就会被调用。但是,authService.user 不会获取用户的新值。它仍然具有初始值(jdoe/Dreamland)。我尝试将 var 服务更改为 user: function() { return user; },但这没有帮助。
  • 对于用户来说,你应该做的差不多。检查我更新的答案。
  • 不幸的是,这不起作用。我已经编辑了我之前的评论说,可能你没有阅读编辑后的版本。无论如何,请参阅@Agop 的答案,这是可行的。
猜你喜欢
  • 2010-10-23
  • 1970-01-01
  • 2011-04-27
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-13
  • 1970-01-01
相关资源
最近更新 更多