如何在 AngularJS 中存储当前用户上下文?

我有一个 AuthService,它登录一个用户,返回一个用户 json 对象。我想要做的是设置这个对象,让所有的更改都反映到整个应用程序中(登录/注销状态) ,而不需要刷新页面。

如何使用 AngularJS 实现这一点?

62975 次浏览

The easiest way to accomplish this is by using a service. For example:

app.factory( 'AuthService', function() {
var currentUser;


return {
login: function() { ... },
logout: function() { ... },
isLoggedIn: function() { ... },
currentUser: function() { return currentUser; }
...
};
});

You can then reference this in any of your controllers. The following code watches for changes in a value from the service (by calling the function specified) and then syncs the changed values to the scope.

app.controller( 'MainCtrl', function( $scope, AuthService ) {
$scope.$watch( AuthService.isLoggedIn, function ( isLoggedIn ) {
$scope.isLoggedIn = isLoggedIn;
$scope.currentUser = AuthService.currentUser();
});
});

And then, of course, you can use that information however you see fit; e.g. in directives, in templates, etc. You can repeat this (customized to what you need to do) in your menu controllers, etc. It will all be updated automatically when you change the state on the service.

Anything more specific depends on your implementation.

Hope this helps!

I would amend the good response of Josh by adding that, as an AuthService is typically of interest of anyone (say, anyone but the login view should disappear if nobody is logged), maybe a simpler alternative would be to notify interested parties using $rootScope.$broadcast('loginStatusChanged', isLoggedIn); (1) (2), while interested parties (such as controllers) would listen using $scope.$on('loginStatusChanged', function (event, isLoggedIn) { $scope.isLoggedIn = isLoggedIn; }.

(1) $rootScope being injected as an argument of the service

(2) Note that, in the likely case of a asynchronous login operation, you'll want to notify Angular that the broadcast will change things, by including it in a $rootScope.$apply() function.

Now, speaking of keeping the user context in every/many controllers, you might not be happy listening for login changes in everyone of them, and might prefer to listen only in a topmost login controller, then adding other login-aware controllers as children/embedded controllers of this one. This way, the children controller will be able to see the inherited parent $scope properties such as your user context.