Angular UI Router - 重定向根本不起作用

8
我正在使用ui.router来进行Angular应用程序的路由。有一个典型的登录场景,如果用户未登录,我会将他重定向到登录URL。如果不使用ui.router库,这将通过$routeChangeStart事件结合$location.path正常工作。现在,我正在使用$stateChangeStart事件结合$state.go,但什么都没有起作用!它也会使我的浏览器陷入无限循环。我从其他来源了解到这是一个已知的问题,而且没有任何建议的解决方案适用于我。此外,$location.path也无法重定向到登录页面。
以下是我的路径配置:
 .config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
    $stateProvider
        .state('main', {
            url: '/',
            templateUrl: 'views/main.html',
            controller: 'MainCtrl'
        })
        .state('about', {
            url: '/about',
            templateUrl: 'views/about.html',
            controller: 'AboutCtrl'
        })
        .state('login', {
            url: '/login',
            templateUrl: 'views/loginform.html',
            controller: 'LoginCtrl'
        });
    $urlRouterProvider.otherwise("/");
}])

我的run方法:

.run(['$state', '$rootScope', '$location', function($state, $rootScope, $location) {
    //Check when routing starts
    //event, next, current
    $rootScope.$on( '$stateChangeStart', function(e, toState, toParams, fromState, fromParams) {
        //Redirect to login if the user is not logged in
        if (!isUserLoggedIn) {

            //Some suggestion
            //e.preventDefault();
            console.log('Not logged in');

            //Infinite loop, kills my browser!
            $state.go('login');
            $state.transitionTo('login');

            //Some suggestion
            $state.go('login', { url: '/login'});

            //Doesn't work
            $location.path('/login');

            //$location.path( $state.href('login');
            console.log('Redirected');
        }
    });

1
isUserLoggedIn 定义在哪里? - Phil
我有一个认证服务,由于一些官方原因,我在这段代码中跳过了它。它在默认路由下运行良好。 - Rutwick Gangurde
2个回答

9
这里需要做的是,如果状态为“登录”,则不要重定向。只需要进行简单的调整即可。
$rootScope.$on( '$stateChangeStart', function(e, toState  , toParams
                                               , fromState, fromParams) {

    var isLogin = toState.name === "login";

    if(isLogin){

       return; // no need to redirect anymore 
    }
    ...

另外,我们应该使用 event.preventDefault(); 来调用 $state.go('login');

 ...
 // also prevent default on redirect
 $state.go('login');
 event.preventDefault(); 
 ...

请查看这个问答:如何解决'最大调用栈大小超出限制'的 AngularJS 问题,还有一个类似解决方案的plunker

但是我的登录标志实际上是一个返回布尔值的函数,并且它是某个服务的一部分。我该如何在这种情况下使用它?此外,无限循环不会出现在任何地方吗? - Rutwick Gangurde
太好了!preventDefault在事件处理程序中起作用,现在重定向到登录页面正常工作。但是,在我的注销函数中,我使用$state.go重定向到登录页面,它仍然导致循环。注销由按钮点击触发,因此我可以使用preventDefault。 - Rutwick Gangurde
1
请不要误解我的意思。如果可以的话,请您放慢速度,深呼吸一下;)这并不应该很难。只需要考虑您的应用程序。如果有注销...重定向到“主页”或“首页”,只需在开头添加这些条件,如(如果登录或如果主页或如果首页...)返回...不要重定向。这只是更精确的设置。这有帮助吗?我相信您很快就能做到。您已经接近成功了;) - Radim Köhler
谢谢,你真的让我思考了! :) 现在几乎完成了。还有一个问题,如果用户已登录,如何保持在当前页面? - Rutwick Gangurde
让我们在聊天中继续这个讨论 - Rutwick Gangurde
显示剩余3条评论

1
我使用了类似于这个的东西:

MyApp.run(['$rootScope', '$state', function ($rootScope, $state) {
  // The event
  $rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {
    // Is user already logged in?
    var isUserLoggedIn = $rootScope.isUserLoggedIn();

    if (isUserLoggedIn) {
      // don't let user visit login state, he's already logged in.
      $state.go('home');
      // preventDefault as described in @radim's answer
      e.preventDefault();
    } else if (toState.name === "login") {
      // user is not logged in and is not going to login state right now, send him there first.
      $state.go('login');
      // preventDefault as described in @radim's answer
      e.preventDefault();
    }
  });
}]);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接