如何在Angular.js中延迟路由定义?

33

在用户登录之前,我已经配置了一些基本路由,这些路由对所有用户都可用:

App.config(function ($routeProvider) {
    $routeProvider.
        when('/login', { templateUrl: 'views/login.html', controller: PageStartCtrl.Controller }).
        otherwise({ redirectTo: '/login' });
});

所以用户唯一能做的就是登录。用户登录后,我想注册额外的路由,例如:

$http
  .post('api/Users/Login', {   User: userName, Password: userPassword })
  .success(function (response : any) {
    App.config(function ($routeProvider) {
      $routeProvider
        .when('/dashboard', 
              { templateUrl: 'part/dashboard.html', 
              controller: DashboardCtrl.Controller });
  });

然而,我认为我应该只调用.config方法一次,因为$routeProvider是全新的实例,对/login路由一无所知。进一步的调试表明,在解析视图更改时使用了$resourceProvider的第一个实例。

问:有没有办法稍后注册路由?

来自Add routes and templates dynamically to $routeProvider的解决方案可能有效,但相当丑陋(包含全局变量nastyGlobalReferenceToRouteProvider)。

2个回答

47

由于路由是在提供程序级别上定义的,因此通常新路由只能在配置块中定义。问题在于,在配置块中所有重要服务仍未定义(最显著的是 $http)。因此,表面上看起来我们无法动态定义路由。

现在,实际上很容易在应用程序生命周期的任何时刻添加/删除路由!查看 $route源代码,我们可以看到所有路由定义都简单地保存在 $route.routes 哈希表中,可以像下面这样随时进行修改(简化示例):

myApp.controller('MyCtrl', function($scope, $route) {    
    $scope.defineRoute = function() {
        $route.routes['/dynamic'] = {templateUrl: 'dynamic.tpl.html'};
    };
});

这是jsFiddle演示它的链接:http://jsfiddle.net/4zwdf/6/

实际上,如果我们想接近AngularJS所做的事情,路由定义逻辑应该更加复杂,因为AngularJS还定义了一个重定向路由来正确处理以/结尾的路由(使其有效可选)。

因此,虽然上述技术将起作用,但我们需要注意以下几点:

  • 此技术取决于内部实现,如果AngularJS团队决定更改路由定义/匹配方式,则可能会出现问题
  • 还可以使用$route.routes定义otherwise路由,因为默认路由存储在相同哈希下的null键中。

在“旧”的日子里,路由是即时定义的,但AngularJS团队有意更改了它,以便您只能静态地预先定义路由。我想问题在于如果您修改与当前URL匹配的路由,则必须触发路由更改... - Pete BD
我认为路由的未来应该能够应对这种情况。也许它正在等待新的模块架构,允许动态加载模块? - Pete BD
1
是的,确实需要小心地定义与当前URL匹配的路由(实际上可以在jsFiddle中看到这个问题)。另一个问题是我们无法动态定义新控制器(但这更是当前模块系统的一般问题)。无论如何,我认为以上就是我们在当前路由系统中所能达到的极限了。 - pkozlowski.opensource
谢谢,已点赞。稍后加载控制器是可能的(只需加载一个带有一堆“控制器函数”的js脚本)。但是有一个小限制,就是不可能将它们作为函数在路由中引用。必须将其作为字符串引用({ templateUrl: .., controller: 'myController'},而不是{... controller : myController }),因为在路由设置期间,控制器尚未加载,因此myController未定义。 - stej
我会等一段时间,如果什么都没有改变,我会接受你的回答。谢谢。 - stej
显示剩余2条评论

6
我发现@pkozlowski.opensource的答案只适用于angularjs 1.0.1。然而,在后面的版本中,当angular-route.js成为独立文件时,直接设置$route就不起作用了。
在审查代码后,我发现$route.routes的键不再用于匹配位置,而是使用$route.route [key] .RegExp。 在复制when和pathRegExp函数的原始代码后,路由起作用了。请参见jsfiddle: http://jsfiddle.net/5FUQa/1/
  function addRoute(path, route) {
     //slightly modified 'when' function in angular-route.js
  }
  addRoute('/dynamic', {
    templateUrl: 'dynamic.tpl.html'
  });

感谢您的示例代码,这在现代版本的Angular中非常有效。 - Ivan Samovar

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