在Angular 2.0 stable中,我有一个应用程序,我必须根据收到的JSON数据定义/配置路由。我没有任何预定义的路由。我在我的bootstrap组件的构造函数中获取此数据。
我怎样才能实现这一目标?有可能吗?
答案 0 :(得分:5)
我实现这一目标的方法是在引导角度应用程序之前加载路由。这样,当应用程序启动时,所有动态路由都已存在。
所以你必须在platformBrowserDynamic().bootstrapModule(AppModule);
行之前加载main.ts文件中的所有路由。
这是main.ts文件的一个示例,其中路由作为json获取并在引导之前加载。
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { environment } from './environments/environment';
import { AppModule } from './app/app.module';
import { IRoute, IRouteData } from './core/models/route';
import { getComponent } from './core/utils/type-component-mapper';
import { AppRoutes } from './app/app.routes';
export function main() {
console.log('[main]')
return platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
}
switch (document.readyState) {
case 'interactive':
case 'complete':
getRoutes();
break;
case 'loading':
default:
document.addEventListener('DOMContentLoaded', () => getRoutes());
}
function getRoutes() {
// This is where you load the routes json from your api
fetch(environment.apiUrl + '/api/routes/get').then((value: Response) =>
{
return value.json();
}).then((routes: IRoute[]) => {
routes.forEach((o: IRoute) => {
iterate(o);
});
// add each dynamic route to the angular route collection
AppRoutes.unshift(routes[0]);
// all dynamic routes have been added, start the angular app
main();
});
}
function iterate(route: IRoute) {
var children = route.children;
if (children) {
Array.from(children).forEach((o: IRoute) => {
iterate(o)
});
}
var component = getComponent(route.data.type);
if (component) {
route.component = component;
}
}
在此示例中,从api返回的路径json将采用以下形式:
[{
"path" : Shop,
"data" : {
"type" : ShopPage
},
"children" : [{
"path" : Bread,
"data" : {
"type" : ProductPage
}
},
{
"path" : Milk,
"data" : {
"type" : ProductPage
}
}]
}]
将此Json数据解析为IRoute和IRouteData类型:
export interface IRoute {
path: string;
data: IRouteData;
children?: IRoute[];
}
export interface IRouteData {
type: string;
}
导出AppRoutes const也很重要,这样您就可以将新的动态路由推送到AppRoutes集合。它看起来像这样:
export const AppRoutes: Routes = [
{
path: 'hardCodedWelcome',
component: WelcomeComponent
}
];
您还需要为每条路线添加正确的组件。在这种情况下,我会对数据类型属性进行切换以获取正确的组件。这就是我从类型组件映射器文件导入get组件函数的原因:
import { Router, Route } from '@angular/router';
import { Type } from '@angular/core';
import { PageTypes } from './page-types';
import { ShopComponent } from '../../app/Shop/shop.component';
import { ProductComponent } from '../../app/Product/Product.component';
export function getComponent(type: string): Type<any> {
switch (type) {
case PageTypes.Shop: {
return ShopComponent;
}
case PageTypes.Product: {
return ProductComponent;
}
}
}
此处的页面类型只是一个简单的页面类型列表,因此我不必使用魔术字符串。
export const PageTypes = {
Shop: 'ShopPage',
Product: 'ProductPage',
};
当应用程序启动时,路径集合中存在所有动态路径,并且可以通过角度正常解析。这会为应用程序增加一些启动时间,具体取决于有多少路由。但是一旦应用程序启动,所有路由都在config routes集合中,并且对性能没有进一步的影响。
请注意,仅当AOT为false时才有效。
如果你想在AOT中使用它,你必须将路由器注入app.component构造函数,然后添加以下行:
router.resetConfig(allRoutes);
其中所有路由都是您在引导之前将路由推送到的数组。
答案 1 :(得分:0)
可以使用APP_INITIALIZER,即初始化应用程序时执行的功能。
有一篇很棒的文章关于在初始化应用时从API获取路线https://long2know.com/2017/11/angular-dynamic-routes-and-application-initialization/
基本上,您必须创建一个从API获取数据(路由)的服务,在AppModule中创建工厂并将其添加到providers数组中。我上面提到的文章非常清楚地描述了它。