Angular 2 的异步加载路由数据和构建路由指令

Posted

技术标签:

【中文标题】Angular 2 的异步加载路由数据和构建路由指令【英文标题】:Async load routes data and build route instruction for Angular 2 【发布时间】:2016-07-25 14:23:27 【问题描述】:

我尝试从 angular2 动态构建路由(从服务器获取路由配置),然后解析它并为组件路由生成指令(我有父路由配置和子路由到不同的组件,因为我不知道如何定义将子组件路由到一个 main.app.ts 文件中)。

问题是当应用程序启动并尝试创建路由配置和 routeGenerator 尚未构建路由(异步延迟)可以t parse routes data (because async delay, so routesData undefined now) and app is crashig. I dont 知道该怎么做。寻找生命周期引擎盖(有些像 - @Angular2BeforeAppStarted )但什么也没找到。

    import Component, Input, OnChanges from 'angular2/core';
import RouteConfig, RouterOutlet, ROUTER_DIRECTIVES, Router from 'angular2/router';
/* ------- !Angular 2 native components  ---------*/
import routeGenInstance from '../../config/routes/patient_routes';


protected const BUILT_MODULE_PATH: string = '/built/modules/patients/';

@Component(
  template: `
    <router-outlet ></router-outlet>
  `,
  directives: [RouterOutlet, ROUTER_DIRECTIVES]
)
@RouteConfig(routeGenInstance.getRouteDefinitions())

export class PatientsComponent 
  @Input();

  constructor() 


我也尝试以相同的方式更新路线(但应用程序立即崩溃,因为导航组件中的导航链接没有正确的链接方式)

import RouteConfig, RouterOutlet, ROUTER_DIRECTIVES, Router from 'angular2/router';

     constructor(
        private router: Router
         ) 
        router.config([
             routeGenInstance.getRoutesDefinition()
        ])
      

我的路由定义使用异步加载器,因此它们是正确的并且可以在没有异步延迟的情况下工作。我不知道如何让 Angular 等待我的路线定义并开始运行应用程序。

请帮帮我。谢谢。

UPD:

@Thierry 再次感谢您的帮助。你真棒,我的朋友和导师。最后一个问题(最后一个)。你能告诉我如何将 routeConfig 定义到一个带有子子路由定义的应用程序文件中吗? 它的意思。我有进入应用程序文件的主要级别路由


  path: '/',
  name: 'Dashboard',
  component: DashboardComponent,
  useAsDefault: true
,

  path: '/patients/...',
  name: 'Patients',
  component: PatientsComponent
,

和患者子路由进入患者组件(@RouteConfig)


  path: '/',      // root is appRoot/patients/...
  name: 'PatientsList', component...,
  
  "name": "Chart",
  "path": "/chart/:id", component...
,

如何将此路由配置仅定义到一个 app.file 中? (如何在一个文件中配置带有子路由的路由)?

【问题讨论】:

RouterOutlet已包含在ROUTER_DIRECTIVES中,无需再次添加。 routeGenInstance.getRouteDefinitions() 长什么样子?它返回什么? 【参考方案1】:

一个选项可能是在引导您的应用程序之前获取您的配置。

var injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
var http = injector.get(Http);

http.get('routes.json').map(res => res.json())
  .subscribe(data => 
    bootstrap(AppComponent, [
      HTTP_PROVIDERS
      provide('routesConfig',  useValue: data )
    ]);
  );

然后你可以通过依赖注入和同步的方式访问路由配置:

@Component(
  (...)
)
export class AppComponent 
  constructor(@Inject('routesConfig') private routesConfig, private router:Router) 
    // Configure here your routes
  

这两个问题可以帮助你:

How to bootstrap an Angular 2 application asynchronously angular2 bootstrap with data from ajax call(s)

编辑

您可以利用 Observable.forkJoin 方法从不同的请求中加载您的路由配置:

var injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
var http = injector.get(Http);

Observable.forkJoin([
  http.get('mainRoutes.json'),
  http.get('childRoutes.json')
])
.map(responses => 
  return 
    main: res[0].json(),
    children: res[1].json()
   ;
 )
  .subscribe(data => 
    bootstrap(AppComponent, [
      HTTP_PROVIDERS
      provide('routesConfig',  useValue: data )
    ]);
  );

编辑1

我认为你可以尝试这样的事情:

[
  
    path: '/patients/...',
    name: 'Patients',
    component: PatientsComponent,
    childRoutes: [
      
        path: '/',      // root is appRoot/patients/...
        name: 'PatientsList', component...
      ,
      (...)
    ]
  
]

但是你需要根据你要处理的提示,对内容进行拆分得到不同的元素:

一个用于根:

[
  
    path: '/patients/...',
    name: 'Patients',
    component: PatientsComponent
  
]

几个给孩子的。以患者为例:

[
  
    path: '/',      // root is appRoot/patients/...
    name: 'PatientsList', component...
  ,
  (...)
]

【讨论】:

Thierry 感谢您的回答,我现在就试试这个。但我对此还有一个问题。现在我将我的路由配置保存到 2 个文件中,并将其包含到 2 个不同的组件中(一个 - app.main 的主路由,第二个 - 子路由,用于患者(例如))。 Its possible join its 路由配置并仅在 app.ts 文件中引导它? 不客气!是的,您可以为此利用 Observable.forkJoin 方法...我更新了答案(注入保持不变)。 非常感谢蒂埃里。那么,当我收到这些数据并将其提供给主应用程序时,我是否必须在应用程序构造函数中使用 router.config 而不是 @RouteConfig 装饰器?因为我不知道如何从 @RouteConfig 的 Injector 获取配置。抱歉,请教一些愚蠢的问题。 我更新了我的第一篇文章,向您@Thierry 提出了问题。请你看看这个好吗? 我了解你 =) 谢谢。你是绝对正确的(我的 JSON 和你的例子一样)。但是是否可以为主应用程序设置 route.config。文件(和设置 route.config - 用于患者列表)仅在 主应用程序文件 中(在 patientListComponenr 中没有路由配置?(在应用程序引导后,我想将路由配置设置到应用程序文件中(对于父应用程序, ang child - patientsList)。它是真实的吗?如果它是真实的,如何做到这一点(当进入 route.config 时,我们只需要为一个组件传递一个路由器定义)。我完全坚持这一点。【参考方案2】:

在新路由器(&gt;= RC.3)https://angular.io/docs/js/latest/api/router/index/Router-class.html#!#resetConfig-anchorresetConfig可以使用

router.resetConfig([
  path: 'team/:id', component: TeamCmp, children: [
    path: 'simple', component: SimpleCmp ,
    path: 'user/:name', component: UserCmp 
 ] 
]);

另见https://github.com/angular/angular/issues/9472#issuecomment-229230093

您可以通过提供 SystemJsComponentResolver 来异步加载组件。 现在,您可以使用 resetConfig 异步加载路由并强制更新配置。 一旦 AppModules 处于 master 状态,我们将利用它们来实现子配置的异步加载。

https://github.com/angular/angular/issues/11437#issuecomment-245995186 提供了一个RC.6 Plunker

【讨论】:

【参考方案3】:

检查这个: 动态异步路由器

https://github.com/Longfld/DynamicalAsyncRouter

【讨论】:

【参考方案4】:

使用 Observables/Promises 提供路由转换不是一个可靠的解决方案,因此 Angular 路由器需要 Route[] 或 Routes,但 HTTP 请求只能返回一个 Observable/Promise。

Angular 应用程序已初始化,但路由转换的检索过程仍使用 Observables/Promises 继续进行。

正如 Thierry Templier 所说,在引导应用程序之前获取配置可以解决问题。

另外,请查看 github 上的 @ngx-i18n-router/core。

【讨论】:

以上是关于Angular 2 的异步加载路由数据和构建路由指令的主要内容,如果未能解决你的问题,请参考以下文章

Angular默认子路由未加载父组件

Heroku 和 Angular 路由

路由器插座的Angular 2延迟渲染

vue 路由懒加载

vue路由懒加载

延迟加载到Angular 2中的空路由以外的路由