AngularJS - 如何公开服务属性

时间:2015-07-11 14:37:53

标签: angularjs angularjs-service

我很难从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>

2 个答案:

答案 0 :(得分:5)

执行此操作时:

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 :(得分: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()