NgModule注册路由分根模块(AppModule)与子模块注册路由,只有根模块AppModule才能使用forRoot()方法。
- 主模块 RouterModule.forRoot()方法
- 子模块 RouterModule.forChild()方法
需要执行导航时,可以使用router对象用来进行导航
- this.router.navigate(['hero',id]);
- this.router.navigate(['hero']);
当一些路由带有参数(包括必须参数和可选参数),我们如何在导航组件获取这个参数?
ActivatedRoute接口为我们提供了包含你需要从当前路由组件中获得的全部信息,正如你可以从RouterState中获得关于其它激活路由的信息。
ActivatedRoute属性
PropertyName | explain |
---|---|
url | 该路由路径的Observable对象。它的值是一个由路径中各个部件组成的字符串数组。 |
data | 该路由提供的data对象的一个Observable对象。还包含从resolve守卫中解析出来的值。 |
params | 包含该路由的必选参数和可选参数的Observable对象。 |
queryParams | 一个包含对所有路由都有效的查询参数的Observable对象。 |
fragment | 一个包含对所有路由都有效的片段值的Observable对象。 |
outlet | RouterOutlet的名字,用于指示渲染该路由的位置。对于未命名的RouterOutlet,这个名字是primary。 |
routeConfig | 与该路由的原始路径对应的配置信息。 |
parent | 当使用子路由时,它是一个包含父路由信息的ActivatedRoute对象。 |
firstChild | 包含子路由列表中的第一个ActivatedRoute对象。 |
children | 包含当前路由下激活的全部子路由。 |
Component引入ActivatedRoute
import { ActivatedRoute, Params} from '@angular/router';
注入
constructor(private route: ActivatedRoute, params: Params)
生命周期钩子中获取、解析数据
ngOnInit(){
this.route.params...
}
学习这一部分内容前我们先来看一下结构,心里对结构有个数,比较容易理解。
结构 | 说明 |
---|---|
AppModule | 根模块 |
AppRoutingModule | 根模块路由 |
AppComponent | 根组件 |
ParAComponent | 组件ParA |
ParBComponent | 组件ParB |
- | - |
ChildModule | 特性模块 |
ChildRoutingModule | 特性模块路由 |
ChildAComponent | 组件ChildA |
ChildBComponent | 组件ChildB |
下面再来看一下各部分的内容
特性模块路由
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ChildAComponent } from './child-a.component';
import { ChildBComponent } from './child-b.component';
const childRoutes: Routes = [
{ path: 'childs', component: ChildAComponent },
{ path: 'childs/:id', component: ChildBComponent }
];
@NgModule({
imports: [
RouterModule.forChild(childRoutes)
],
exports: [
RouterModule
]
})
export class ChildRoutingModule { }
特性模块
import { NgModule } from '@angular/core';
import { ChildRoutingModule } from './heroes-routing.module';
import { ChildAComponent } from './child-a.component';
import { ChildBComponent } from './child-b.component';
@NgModule({
imports: [
ChildRoutingModule
],
declarations: [
ChildAComponent,
ChildBComponent
]
})
export class ChildModule {}
特性模块说明:特性模块路由中包含组件ChildA和ChildB,ChildA是一个列表,ChildB是列表项,通过id来关联。
根模块路由
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ParAComponent } from './par-a.component';
import { ParBComponent } from './par-b.component';
const appRoutes: Routes = [
{ path: 'parA', component: ParAComponent },
{ path: 'parB', component: ParBComponent },
{ path: '', redirectTo: 'childs', pathMatch: 'full' }
];
@NgModule({
imports: [
RouterModule.Root(appRoutes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
根模块
import { NgModule } from '@angular/core';
import { ChildModule } from './child/child.module';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ParAComponent } from './par-a.component';
import { ParBComponent } from './par-b.component';
@NgModule({
imports: [
ChildModule,
AppRoutingModule
],
declarations: [
AppComponent,
ParAComponent,
ParBComponent
].
bootstrap: [ AppComponent ]
})
export class AppModule {}
根模块说明:根模块路由器中包含三个路由:ParA,ParB,子模块。
重点
如果单独看根模块或特性模块,结构很清晰,没有什么问题。但是他们是如何关联的呢?我们来分析一下。
首先,根模块路由将redirectTo设置为"childs"对应的ChildAComponent,所以根路由中,我们不必在引用ChildAComponent组件,而是直接用特性模块路由来提供组件。
这里很重要,因为一个组件只能有一个所有者,不能同时属于两个模块。
但是angular中是如何寻找特性模块路由的呢?在AppModule中,引入了特性模块ChildModule,特性模块中又引入了特性模块路由,这样便把所有内容都连接起来,可以走通了。
另外需要注意的是,根模块的路由器模块注册时使用的是RouterModule.ForRoot(),而特性模块中注册时使用的是RouterModule.forChild(),只有根模块的路由器模块注册才使用forRoot。
由特性模块提供的路由将会被路由器和它们导入的模块提供的路由组合在一起。这让我们可以继续定义特性路由,而不用修改主路由配置。
主模块与特性模块解耦。
另外一个重点 - 特性模块在哪显示?
先说根模块的路由,导航的视图是在appComponent中的 元素后显示,而特性模块属于根模块路由的一项,所以特性模块配置的组件视图也是在这里显示。
使用路由时,除了传递必须参数,让程序稳定执行外,还可以传递可选参数。
可选参数可以用来提升用户体验,让页面呈现更好的效果。而必须参数才是我们正常执行程序的根本。
向外传递可选参数
gotoBack(){
this.router.navigate(['/parA',{ id: 15, name: cyz }]);
}
这样我们在导航至parA视图时,就向这个视图传递了一个object
接收可选参数
constructor(private route: ActivatedRoute){ }
ngOnInit(){
this.route.params.switchMap((params: Params) => {
this.id = params['id'];
let name = params['name'];
})
}
在接收参数的组件中,先要注入ActivatedRoute,因为我们需要的参数是存在与这个接口中,然后在生命周期钩子中获取参数。
这里的switch暂时先不需要详细了解,只知道它帮我们解析我们获取的数据即可。后面会学习到关于它的知识。