在搭建一个项目的时候,了解下来,Angular的路由功能还是有点绕的,做个总结;文章会通过实际的例子和代码来介绍,不单纯是一些理论的东西;文章第一部分会说下jhipster生成的框架默认的路由的加载,然后第二部分针对有特殊的需求,说下自己的解决方法;
首先要明确一个问题:路由加载的组件会填充它的parent的compent对应的html里面的router-outlet标签中,如果没找到parent的compent,会继续往上面接着找,最终一般会找到root compent对应的html中的router-outlet标签,一般为index页面;
1.Jhipster路由
index页面的默认内容,里面只加载了jhi-main 这个compoent;
<jhi-main></jhi-main>
<noscript>
<h1>You must enable javascript to view this page.</h1>
</noscript>
JhiMainComponent具体内容如下
<jhi-page-ribbon></jhi-page-ribbon>
<div>
<router-outlet name="navbar"></router-outlet>
</div>
<div class="container-fluid main-content-height">
<div class="card jh-card height-100">
<router-outlet></router-outlet>
<router-outlet name="popup"></router-outlet>
</div>
<!--<jhi-footer></jhi-footer>-->
</div>
然后所有的页面内容都会填充到<router-outlet></router-outlet>里面去。看下jhipster生成的框架的默认的路由情况,首先是App.module.ts,会加载下面的这些module
imports: [
BrowserModule,
AiopsAppRoutingModule,
Ng2Webstorage.forRoot({prefix: 'jhi', separator: '-'}),
AiopsSharedModule,
AiopsCoreModule,
AiopsHomeModule,
AiopsAccountModule,
AiopsEntityModule,
BrowserAnimationsModule,
// jhipster-needle-angular-add-module JHipster will add new module here
NgZorroAntdModule
],
这些module里面又会加载子module,这里以AiopsAccountModule为例,下面是他的module导入的路由
const ACCOUNT_ROUTES = [activateRoute, passwordRoute, passwordResetFinishRoute, passwordResetInitRoute, registerRoute, settingsRoute, loginRoute];
export const accountState: Routes = [
{
path: '',
children: ACCOUNT_ROUTES
}
];
可以看到又导入了一些子路由。
注意:
1>这里的path是空,如果不为空,比如为"account",那么下面的路由整个地址就是"account/password";
2>至于这里为什么要把路由定义成一个静态的路由数组那?主要是为了可以方便的导入到多个模块使用;
3>这里AccountState只有path没有component,如果有component的话,下面的这些路由会插入到这个component对应的页面中;
2.基于Homecompoent添加菜单栏
现在的需求页面是个左右结构,左边是菜单栏,右边的内容会根据左边的链接变化而变化,这种情况下,考虑HomeComponent中添加左边菜单栏的页面内容,然后右边部分根据左边点击的url不同,嵌入不同的路由页面填充进去;home.component.html内容如下所示,标红的是左边菜单项,下面是一个router-outlet的占位符
然后是home.route.ts文件,里面会导入子路由
const HOME_ROUTES = [questionRoute, personalCenterRoute];
export const HOME_ROUTE: Route = {
path: 'home',
component: HomeComponent,
data: {
authorities: [],
pageTitle: 'Welcome, Java Hipster!'
},
children: HOME_ROUTES,
canActivate: [UserRouteAccessService]
};
这样访问personalCenterRoute中的路由就会加载home component中的左边的导航栏内容;personalCenterRoute内容如下所示
export const personalCenterRoute: Route = {
path: 'personal-center',
children: [
{
path: 'my-submit',
component: MySubmitComponent,
data: {
authorities: ['ROLE_SERVER', 'ROLE_PROFESSOR'],
pageTitle: '我的提交'
},
canActivate: [UserRouteAccessService]
}
]
};
结果如下所示
这里路由定义定义为const变量就是方便多个模块导入使用;这里可以测试下
@NgModule({
imports: [AiopsSharedModule, RouterModule.forChild([personalCenterRoute])],
declarations: [MySubmitComponent],
entryComponents: [],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class PersonalCenterModule {
}
这里把PersonalCenterModule也导入RouterModule.forChild([personalCenterRoute])这个路由,注意一点,PersonalCenterModule不是在home的路由下面,而是在entityModule下面的;会直接嵌入到最上面的router-out里面去,所以是不会有左边的导航菜单的,如图所示
两者的区别是地址不同:
http://localhost:9000/#/home/personal-center/my-submit #会先加载home页面,然后子路由内容嵌入到home页面中去
http://localhost:9000/#/personal-center/my-submit #直接将内容嵌入到index页面中去
但是同一个子路由被不同的module加载展示出来了,这就是把路由定义成const的原因,方便引入到不同的module中去加载;关键是看当前路由的子组件是会填充到哪个parent的compoent对应的页面中去