我正在使用AngularJS ui-router。我正在尝试为未经身份验证的用户实施保护路由。我正在检查用户是否已登录$stateChangeStart
。如果用户未登录,则重定向到登录状态。
但是当我在$state.go("login")
处理程序中使用stateChangeStart
时,处理程序代码进入无限循环并且出现控制台错误" RangeError:超出最大调用堆栈大小"
以下是我的代码:
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams) {
var allowedStates = ["signup","confirmaccount","resetPassword"];
if(!$window.localStorage.getItem('userInfo') && !(allowedStates.includes($state.current.name)))
{
$state.go("login");
}
}
);
以下是控制台错误的屏幕截图。
答案 0 :(得分:2)
防止默认行为并在不使用$state.current.name
的情况下检查允许状态,因为toState
已经是$stateChangeStart
的参数
更新
我认为你需要一个No State Change
逻辑,而不是重定向到始终登录。
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams) {
var noChangeStates = ["login", "signup", "confirmaccount", "resetPassword"];
var noStateChange = noChangeStates.indexOf(toState.name) > -1;
if (noStateChange) {
return;
}
//Check for Allowed or Not Allowed logic here then redirect to Login
if (!$window.localStorage.getItem('userInfo')) {
event.preventDefault();
$state.go("login")
}
}
);
请注意,您还应添加"登录"无状态改变
答案 1 :(得分:0)
但是当我在stateChangeStart处理程序中使用$ state.go(" login")时,处理程序代码进入无限循环并且出现控制台错误" RangeError:超出最大调用堆栈大小&#34 ;
您似乎总是致电$state.go("login");
您可以查看toState
和fromState
,以避免拨打额外时间$state.go("login");
类似的东西:
if(!$window.localStorage.getItem('userInfo')
&& !(allowedStates.includes($state.current.name))
&& fromState.name !== 'login'
){
event.preventDefault();
$state.go("login");
}
答案 2 :(得分:0)
使用stateChange事件不是处理它的最佳方法。实际上,它做了什么:
在更改状态之前检查会更好。为此,您可以使用ui-router' resolve
:
$stateProvider
.state('login', { // Login page: do not need an authentication
url: '/login',
templateUrl: 'login.html',
controller: 'loginCtrl',
})
.state('home', { // Authenticated users only (see resolve)
url: '/home',
templateUrl: 'home.html',
controller: 'homeCtrl',
resolve: { authenticate: authenticate }
});
function authenticate($q, user, $state, $timeout) {
if (user.isAuthenticated()) {
// Resolve the promise successfully
return $q.when()
} else {
// The next bit of code is asynchronously tricky.
$timeout(function() {
// This code runs after the authentication promise has been rejected.
// Go to the log-in page
$state.go('logInPage')
})
// Reject the authentication promise to prevent the state from loading
return $q.reject()
}
}
另见this answer。