AngularJS - 需要$ routeChangeStart和$ locationChangeStart的某种组合

Thi*_*ham 21 javascript routes angularjs angularjs-directive angularjs-routing

我的问题实际上与这里发现的问题非常相似:

AngularJs - 取消路线更改事件

简而言之,我正在使用$ routeChangeStart并尝试使用$ location更改当前路由.当我这样做时,控制台告诉我原始页面仍然加载并被新页面快速覆盖.

提供的解决方案是使用$ locationChangeStart而不是$ routeChangeStart,这应该可以防止额外的重定向.不幸的是,我在$ routeprovider中使用了我需要在更改路径时访问的其他数据(我用它来跟踪页面限制).这是一个例子......

$routeProvider.
    when('/login', { controller: 'LoginCtrl', templateUrl: '/app/partial/login.html', access: false}).
    when('/home', { controller: 'HomeCtrl', templateUrl: '/app/partial/home.html', access: true}).
    otherwise({ redirectTo: '/login' });


$rootScope.$on('$routeChangeStart', function(event, next, current) {
    if(next.access){
        //Do Stuff
    }
    else{
        $location.path("/login");
        //This will load the current route first (ie: '/home'), and then
        //redirect the user to the correct 'login' route.
    }
});
Run Code Online (Sandbox Code Playgroud)

使用$ routeChangeStart,我可以使用"next"和"current"参数(请参阅AngularJS - $ route)作为对象来检索我的"访问"值.使用$ locationChangeStart,这两个参数返回url字符串,而不是对象.所以似乎无法检索我的"访问"值.

有没有什么方法可以将$ locationChangeStart的重定向停止功能与$ routeChangeStart的对象灵活性结合起来,以实现我的需求?

Mar*_*ier 22

想到的一种方法是尝试使用resolve参数:

var resolver = function(access) {
  return {
    load: function($q) {
      if (access) { // fire $routeChangeSuccess
        var deferred = $q.defer();
        deferred.resolve();
        return deferred.promise;
      } else { // fire $routeChangeError
        return $q.reject("/login");
      }
    }
  }
}

$routeProvider.
  when('/login', { controller: 'LoginCtrl', templateUrl: '/app/partial/login.html', resolve: resolver(false)}).
  when('/home', { controller: 'HomeCtrl', templateUrl: '/app/partial/home.html', resolve: resolver(true)}).
  otherwise({ redirectTo: '/login' });
Run Code Online (Sandbox Code Playgroud)

请注意,我没有测试上面的代码,但我在我的项目中做了类似的事情.


tam*_*are 14

我自己也遇到了同样的情况,我的解决方案与OP打算做的事情保持一致.

我使用$locationChangeStart事件和$route服务.通过访问$route.routes,我得到了所有定义的路径对象$routeProvider.

.run(function($rootScope, $route, $location) {
  $rootScope.$on('$locationChangeStart', function(ev, next, current) {
    // We need the path component of `next`. We can either process `next` and 
    // spit out its path component, or simply use $location.path(). I go with
    // the latter.
    var nextPath = $location.path();
    var nextRoute = $route.routes[nextPath]

    console.log(nextRoute.access); // There you go!
  });
})
Run Code Online (Sandbox Code Playgroud)

要从绝对URL解析路径组件:

var urlParsingNode = document.createElement('a');
urlParsingNode.href = next;  // say, next = 'http://www.abc.com/foo?name=joe
console.log(urlParsingNode.pathname)  // returns "/foo"
Run Code Online (Sandbox Code Playgroud)

  • 这对于带参数的路由有什么用?喜欢/ article /:articleId? (3认同)

snr*_*rlx 7

从版本1.3.0开始,您实际上可以使用新引入的preventDefault -method.有了它,您可以取消当前路由更改,然后应用您自己的自定义重定向,如此github问题所示:


$rootScope.$on("$routeChangeStart", function (event, next, current) {
    if (next.access) {
      event.preventDefault();
      $rootScope.$evalAsync(function() {
        $location.path('/login');
      });
    }
});
Run Code Online (Sandbox Code Playgroud)

我在自己的项目中实现了这个方法,它运行得很好.希望它可以帮助其他任何偶然发现它的人.