这是一个复杂的问题。 我试图在用户尝试访问需要授权的页面时创建一个returnState。
所以,我在状态对象上创建了一些如下所示的数据:
$stateProvider.state('account', {
url: '/account',
templateUrl: '/app/account/index.tpl.html',
controller: 'AccountController',
controllerAs: 'controller',
data: {
requireLogin: true,
state: 'account' // tells the page to redirect here if not logged in
}
});
然后我有一些代码在stateChangeStart上运行:
.run(['$rootScope', '$state', 'AccountService', function ($rootScope, $state, account) {
// On state change
$rootScope.$on('$stateChangeStart', function (event, toState) {
var data = toState.data; // Get our state data
var requireLogin = typeof data === 'undefined' ? false : data.requireLogin; // Check to see if we have any data and if so, check to see if we need login rights
var user = account.current() // Get our current user
// If we require login rights and we are not authenticated
if (requireLogin && !user.authenticated) {
// Get our current state
var state = data.state || '';
// Stop processing
event.preventDefault();
// redirect to the login page and pass the state parameter
$state.transitionTo('login', { returnState: state });
}
});
}]);
然后在我的loginController上我有这个功能:
self.loginUser = function () {
// Login
self.login = service.login(self.model);
// If we login properly
self.login.promise.then(function (response) {
// If we have a return Url
if (returnState) {
// Go to that url
$state.go(returnState);
} else {
// Otherwise, Redirect to the home page
$state.go('home');
}
});
};
我展示的例子完美无缺。但现在我发现我有更复杂的需求。 我有另一组状态:
$stateProvider.state('designer', {
url: '/:sport/designer',
abstract: true,
templateUrl: '/app/designer/designer.tpl.html',
controller: 'DesignerController',
controllerAs: 'controller'
}).state('designer.team', {
url: '',
templateUrl: '/app/designer/team.tpl.html'
}).state('designer.kit', {
url: '/kit',
templateUrl: '/app/designer/kit.tpl.html'
}).state('designer.design', {
url: '/design',
templateUrl: '/app/designer/design.tpl.html'
}).state('designer.refine', {
url: '/refine',
templateUrl: '/app/designer/refine.tpl.html'
}).state('designer.order', {
url: '/order',
templateUrl: '/app/designer/order.tpl.html'
}).state('designer.save', {
url: '/save',
templateUrl: '/app/designer/save.tpl.html',
data: {
requireLogin: true
}
});
正如你所看到的,这个状态和一些孩子以及最后一个状态(保存)需要用户登录。因为状态继承了父母的参数,我应该能够做到这样的事情:
state: 'designer.save({ sport: :sport })'
但我收到错误声明:
错误:无法解析' desginer.save({sport ::运动})'来自州'登录'
现在我假设这是因为:运动不是作为一个字符串传递,但我已经尝试了很多,我无法让它工作。 有没有更好的方法来处理路线?
我确实尝试使用stateChangeStart函数来获取我们正在移动的状态,但我似乎无法访问它。
答案 0 :(得分:1)
首先,如果我们查看the docs,我们可以看到$state.go
接受以下参数:
我无法看到任何地方提到将参数直接放入州名称是骗取的。所以我们有错误消息的原因。 'designer.save({ sport: :sport })'
不是正确的绝对州名。
因为州继承了父母的参数
这意味着您不仅可以访问它们,还可以在某些情况下自动传递它们:
任何未指定的参数都将从当前继承 定义的参数。例如,这允许进入兄弟状态 共享在父状态中指定的参数。参数 继承只适用于共同的祖先状态,即。 过渡到兄弟姐妹将获得所有参数 父母,过渡到孩子将获得所有当前参数, 等
因此,只要您处于designer
州或其中任何一个州,您就不必提供任何参数。如果你不是,那么你需要找到一种方法将参数作为第二个参数传递给$state.go
。
答案 1 :(得分:0)
感谢user2847643的建议。我实际上想出了一个更好的处理方法。 首先,我将登录状态修改为:
$stateProvider.state('login', {
url: '/account/login',
params: {
returnState: '',
returnParams: {}
},
views: {
// the main template will be placed here (relatively named)
'': {
templateUrl: 'app/account/login/index.tpl.html'
},
// the child views will be defined here (absolutely named)
'register@login': {
templateUrl: 'app/account/login/register.tpl.html',
controller: 'RegisterController',
controllerAs: 'controller'
},
// for column two, we'll define a separate controller
'login@login': {
templateUrl: 'app/account/login/login.tpl.html',
controller: 'LoginController',
controllerAs: 'controller'
}
}
});
如您所见,这接受两个可选参数。 然后我将登录功能修改为:
self.loginUser = function () {
// Login
self.login = service.login(self.model);
// If we login properly
self.login.promise.then(function (response) {
console.log(returnState);
console.log(returnParams);
// If we have a return Url
if (returnState) {
// Go to that url
$state.go(returnState, returnParams);
} else {
// Otherwise, Redirect to the home page
$state.go('home');
}
});
};
现在正确调用 $ state.go 函数传递状态和参数(或空对象)。
我实际上把我的逻辑用于处理我之前展示的 stateChangeStart 绑定中的returnStates,所以现在看起来像这样:
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
var data = toState.data; // Get our state data
var requireLogin = typeof data === 'undefined' ? false : data.requireLogin; // Check to see if we have any data and if so, check to see if we need login rights
var user = account.current() // Get our current user
// If we require login rights and we are not authenticated
if (requireLogin && !user.authenticated) {
// Get our current state
var name = toState.name;
var params = toParams;
// If our state is the login page (i.e. we accessed it directly)
if (name === 'login') {
// Set our state to the homepage
name = 'home';
toParams = {};
}
// Stop processing
event.preventDefault();
// redirect to the login page and pass the state parameter
$state.transitionTo('login', { returnState: name, returnParams: params });
}
});
我们有它。
答案 2 :(得分:0)
感谢r3plica这篇文章。我面临的问题很少,并以下列方式解决。如果我错了,有人可以纠正我。
在$ stateChangeStart事件中,您还需要从State,fromParams传递参数。这用于检查fromState是否未登录,因此您一次又一次地跳过重新加载登录页面。
$ rootScope。$ on('$ stateChangeStart',function(event,toState,toParams,fromState,fromParams){ // var restrictedPage = $ .inArray($ location.path(),['/ landing','/ list','/ landing / users']);
var data = toState.data;
if(typeof toState.data !== 'undefined' && fromState.name !== 'login'){......}
}