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 don
t 知道该怎么做。寻找生命周期引擎盖(有些像 - @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 it
s 路由配置并仅在 app.ts 文件中引导它?
不客气!是的,您可以为此利用 Observable.forkJoin 方法...我更新了答案(注入保持不变)。
非常感谢蒂埃里。那么,当我收到这些数据并将其提供给主应用程序时,我是否必须在应用程序构造函数中使用 router.config 而不是 @RouteConfig 装饰器?因为我不知道如何从 @RouteConfig 的 Injector 获取配置。抱歉,请教一些愚蠢的问题。
我更新了我的第一篇文章,向您@Thierry 提出了问题。请你看看这个好吗?
我了解你 =) 谢谢。你是绝对正确的(我的 JSON 和你的例子一样)。但是是否可以为主应用程序设置 route.config。文件(和设置 route.config - 用于患者列表)仅在 主应用程序文件 中(在 patientListComponenr 中没有路由配置?(在应用程序引导后,我想将路由配置设置到应用程序文件中(对于父应用程序, ang child - patientsList)。它是真实的吗?如果它是真实的,如何做到这一点(当进入 route.config 时,我们只需要为一个组件传递一个路由器定义)。我完全坚持这一点。【参考方案2】:
在新路由器(>= 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 的异步加载路由数据和构建路由指令的主要内容,如果未能解决你的问题,请参考以下文章