如何从$ stateChangeStart访问UI-Router根状态的'resolve'属性?

Rou*_*tor 18 angularjs angular-ui-router

我正在尝试在我的应用程序中实现用户身份验证和访问检查系统,但是我一直在遇到障碍.我想这次我有正确的方法,但我有最后一个障碍.

一点背景:我尝试将所有代码放入$ rootScope.on($ startChangeStart)并且它工作得很糟糕......但它确实有效.路线始终被重定向,但由于后端的验证检查,它显示第一个请求页面1/2秒,然后每次都显示重定向页面.因此,我尝试通过在$ startChangeStart函数的开头调用evt.preventDefault()来"暂停"页面加载,这起作用,但是尝试将用户放回到原始路由之后导致路由器中的无限循环.

因此,经过更多的研究和阅读大量的帖子后,我确定'resolve:'是进行auth检查的正确位置,以确保页面在发生时不加载,然后根据需要从$重定向用户startChangeStart.($ state和event总是在我尝试将它们注入解析函数时未定义)这似乎是获胜的组合.

我的问题:我对我的应用中的root状态有了决心:'main'

这是为了避免代码冗余,但我无法确定如何从$ stateChangeStart函数访问根状态的属性,从而确定解析结果.toState是子状态,而fromState是先前的状态或具有'^'路由的抽象状态...

我是否必须将解决方案放在每个子状态才能使用,或者是否有办法从此处访问根状态?

基本应用设置:

angular.module('App', ['ui.router', 'ui.bootstrap', 'ui.event', 'AngularGM', 'ngResource'])
.config(['$urlRouterProvider', '$stateProvider', function($urlRouterProvider, $stateProvider){
    $urlRouterProvider
        .when('/home', '/')
        .when('', '/')
        .when('/sign-up/joe', '/sign-up')
        .otherwise('/');

    $stateProvider
        .state('main', {
            url: '',
            abstract: true,
            templateUrl: 'views/main.html',
            controller: 'MainCtrl',
            resolve: {
                checkAccess: ['accountService', function(accountService) {
                    accountService.checkAuth(function(){
                        accountService.checkAccess(function (access){
                            return access;
                        });
                    });
                }]
            }
        })
        .state('main.home', {
            url: '',
            abstract: true,
            templateUrl: 'views/home.html',
            controller: 'HomeCtrl'
        })
        .state('main.home.index', {
            url: '/',
            templateUrl: 'views/home/index.html'
        });


.run(['$rootScope', '$state', '$stateParams', 'accountService', function ($rootScope, $state, $stateParams) {
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
        console.dir(toState);
        console.dir(toParams);
        console.dir(fromState);
        console.dir(fromParams);
        if (!toState.checkAccess.allowed) {
            event.preventDefault();
            $state.transitionTo(toState.checkAccess.newState);
        }
    });
}]);
Run Code Online (Sandbox Code Playgroud)

这是对两个状态对象的console.dir()调用的输出:

Object
 name: "main.home.index"
 templateUrl: "views/home/index.html"
 url: "/"
 __proto__: Object

Object
 controller: "PlacesCtrl"
 name: "main.places.search"
 templateUrl: "views/places.html"
 url: "/places"
 __proto__: Object
Run Code Online (Sandbox Code Playgroud)

更新

糟糕,忘了提到AngularJS版本是v1.2.0-rc.2

$ state.current console.dir()

Object
 abstract: true
 name: ""
 url: "^"
 views: null
 __proto__: Object
Run Code Online (Sandbox Code Playgroud)

Den*_*Luz 8

是的,我相信你可以从$stateChangeStart函数中访问root状态.

当我使用纯正的AngularJS时 current.$$route

例如,使用以下路线

.when('/home', {
  title:'Home',
  bodyClass: 'meetings',
  controler: 'HomeCtrl'
})
Run Code Online (Sandbox Code Playgroud)

我可以像这样访问root状态

  $rootScope.$on('$routeChangeSuccess', function (event, current, previous) {

   if (current.$$route) {

     $rootScope.title      = current.$$route.title;

     $rootScope.bodyClass  = current.$$route.bodyClass;
   }

 });
Run Code Online (Sandbox Code Playgroud)

使用ui-router它只是有点不同,因为它被称为$state.current.并且您可以访问与您命中的任何路径相关联的所有属性(例如:$ state.current.url)

所以在你的代码上你可以得到类似的东西

  .run(['$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) {

      $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
          console.log($state.current.url);
      });
  }]);
Run Code Online (Sandbox Code Playgroud)

  • 我的印象是,在stateChangeStart事件之后解析数据已经"解决"...即.如果你调用`event.preventDefault()`那么结果永远不会开始.我可能错了. (2认同)
  • @RhysvanderWaerden,你是对的.`resolve`将在`stateChangeStart`之后触发,如果你正在寻找你的`resolve`来加载你的访问权限,例如页面刷新,那就太晚了.我正在寻找这个问题的解决方案. (2认同)
  • 糟糕,压入太快了.无论如何,我这样做的方法是在解析函数中抛出一个异常,如果权限不够(如果它是400错误,你可能会得到一个错误,如果它是一个'isLoggedIn'类型查询,你可以抛出你自己).然后我在`$ stateChangeError`中捕获它并转发到相应的页面. (2认同)