混淆 $locationChangeSuccess 和 $stateChangeStart [英] Confusing $locationChangeSuccess and $stateChangeStart
问题描述
我正在尝试使用 AngularUI 路由器进行一些身份验证.$urlRouter.sync()
看起来正是我需要的.但是,这仅在我拦截 $locationChangeSuccess
时可用.但是当我这样做时, $state.current.name
是空的,而我希望它是当前状态.
I am trying to do some authentication with AngularUI Router. $urlRouter.sync()
looks like exactly what I need. However, that's only available when I intercept $locationChangeSuccess
. But when I do that, $state.current.name
is empty, whereas I want it to be the current state.
这是我目前的代码:
$rootScope.$on('$locationChangeSuccess', function(event, next, nextParams) {
event.preventDefault();
if ($state.current.name === 'login') {
return userService.isAuthenticated().then(function(response) {
var authenticated;
authenticated = response.authenticated;
return alert(authenticated);
});
}
});
任何关于我做错了什么的提示?
Any pointers as to what I'm doing wrong?
推荐答案
我建议多走UI-Router
方式".我们应该使用 $rootScope.$on('$stateChangeStart'
事件,其中 $state.current
将被正确提供.这里是 一个工作示例
I would suggest to go more "UI-Router
way". We should use $rootScope.$on('$stateChangeStart'
event where $state.current
would be properly provided. Here is a working example
让我们观察简单的(但不是幼稚的) 解决方案,它可以在以后扩展到任何程度.此外,如果您喜欢这种方法,这里有更全面的实现:angular ui-router login authentication
Let's observe simple (but not naive) solution, which could be extended to any degree later. Also if you will like this approach, here is much more comprehensive implementation: angular ui-router login authentication
首先,让我们像这样定义我们的用户服务:
Firstly, let's have our user service defined like this:
.factory('userService', function ($timeout, $q) {
var user = undefined;
return {
// async way how to load user from Server API
getAuthObject: function () {
var deferred = $q.defer();
// later we can use this quick way -
// - once user is already loaded
if (user) {
return $q.when(user);
}
// server fake call, in action would be $http
$timeout(function () {
// server returned UN authenticated user
user = {isAuthenticated: false };
// here resolved after 500ms
deferred.resolve(user)
}, 500)
return deferred.promise;
},
// sync, quick way how to check IS authenticated...
isAuthenticated: function () {
return user !== undefined
&& user.isAuthenticated;
}
};
})
因此,我们使用 async (here $timeout
) 从服务器加载 user
对象.在我们的示例中,它将有一个属性 {isAuthenticated: false }
,用于检查是否已通过身份验证.
So, we use async (here $timeout
) to load user
object form a server. In our example it will have a property {isAuthenticated: false }
, which will be used to check if is authenticated.
还有同步方法 isAuthenticated()
,在加载并允许用户之前,它总是返回 false
.
There is also sync method isAuthenticated()
which, until user is loaded and allowed - always returns false
.
这就是我们对 '$stateChangeStart'
事件的监听器:
And that would be our listener of the '$stateChangeStart'
event:
.run(['$rootScope', '$state', 'userService',
function ($rootScope, $state, userService) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams
, fromState, fromParams) {
// if already authenticated...
var isAuthenticated = userService.isAuthenticated();
// any public action is allowed
var isPublicAction = angular.isObject(toState.data)
&& toState.data.isPublic === true;
if (isPublicAction || isAuthenticated) {
return;
}
// stop state change
event.preventDefault();
// async load user
userService
.getAuthObject()
.then(function (user) {
var isAuthenticated = user.isAuthenticated === true;
if (isAuthenticated) {
// let's continue, use is allowed
$state.go(toState, toParams)
return;
}
// log on / sign in...
$state.go("login");
})
...
我们首先要检查的是用户是否已经加载并通过身份验证(var isAuthenticated = ...
).接下来,我们将为任何公共方法赋予绿色.这是通过状态对象定义的 data {}
属性完成的(请参阅 将自定义数据附加到状态对象)
What we are checking first, is if user is already loaded and authenticated (var isAuthenticated = ...
). Next we will give green to any public method. This is done with the data {}
property of the state object definition (see Attach Custom Data to State Objects)
就是这样.如果像下面的代码片段那样定义状态,我们可以体验:
And that's it. In case of states defined like in a below snippet we can experience:
'public'
,'home'
任何人都可以使用'private'
,'private'
将重定向到登录如果isAuthenticated === false
本示例中的
'login'
提供了如何打开/关闭 isAuthenticated 的快速方法
- the
'public'
,'home'
are allowed to anybody - the
'private'
,'private'
will redirect to login ifisAuthenticated === false
the
'login'
in this example provides quick way how to switch isAuthenticated on/off
// States
$stateProvider
// public
.state('home', {
url: "/home",
templateUrl: 'tpl.html',
data: { isPublic: true },
})
.state('public', {
url: "/public",
templateUrl: 'tpl.html',
data: { isPublic: true },
})
// private
.state('private', {
url: "/private",
templateUrl: 'tpl.html',
})
.state('private2', {
url: "/private2",
templateUrl: 'tpl.html',
})
// login
.state('login', {
url: "/login",
templateUrl: 'tpl.html',
data: { isPublic: true },
controller: 'loginCtrl',
})
检查所有这里
其他一些资源:
这篇关于混淆 $locationChangeSuccess 和 $stateChangeStart的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!