2016-10-14 113 views
4

在Angular 2.0穩定,我有一個應用程序,我必須根據我收到的JSON數據定義/配置路線。我沒有任何預定義的路由。我在我的引導組件的構造函數中獲取這些數據。Angular 2 - 從JSON數據動態路由

我該如何做到這一點?可能嗎?

+0

您可以使用'router.replaceConfig(routes:Routes)',只需根據您的JSON生成路由... – Sasxa

+0

這就是問題所在。那時我沒有組件,因爲我不知道哪一個是必需的。所以我不能製作像{{path:'Page2',component:Page2}'這樣的路線, –

+0

您可以使用'{path:'Page2',loadChildren:「,.module#Page2」}',它只是一個字符串... – Sasxa

回答

2

我實現這一目標的方式是在引導角度應用程序之前加載路線。這種方式,當應用程序啓動時,所有的動態路線已經在那裏。

因此,您必須在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常量也很重要,以便您可以將新的動態路由推送到您的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', 
}; 

當應用程序啓動時,所有動態路由都存在於路由集合中,並且可以通過角度來正常解析。這會爲應用程序增加一些啓動時間,具體取決於有多少路線。但是,一旦應用程序啓動,所有路由都在配置路由集合中,並且不會對性能產生進一步的影響。