路由
Angular是单页程序,路由显示的路径不过是一种保存路由状态的机制,这个路径在web服务器中不存在
<router-outlet></route-outlet>
注意:
- 插入的视图位于router-outlet的下方,而非内部
- 页面中可以有多个具名的router-outlet(辅助插座),但匿名的只能有一个
- 使用得插座过多,反而会导致一些副作用,使路由难以理解。通常情况下,都可以使用子、孙路由的嵌套来解决。
npm i -g http-serve
ng build --prod//编译
http-server . //监听当前目录8080端口
此时强制刷新,找不到页面,返回404,通常需要重定向到index页
ng g c not-found --skipTests -c OnPush -s
创建路由模块
ng g m list --routing
路由定义
const routes:Routes = [
{
path:'',
redirectTo:'home',
pathMatch:'full'
},
{
path:'home',
component:HomeContainerComponent,
children:[
{
path:'',
redirectTo:'hot',
pathMatch:'full',
},
{
path:':tabLink',
component:HomeDetailComponent
}
]
},
{
//前面的都没有符合,通过通配符匹配到最后的404
path:'**',
component:NotFoundComponent
}
]
需要动态传输路由表时,在path的值前面加一个“:”
导入RouterModule
根模块forRoot 子模块forChild
@NgModule({
imports:[RouterModule.forRoot(routes,{enableTracing:true})],
export:[RouterModule]
})
enableTracing可以跟踪url的变化,当导航发生变化时,会打印一堆日志。
为时刻监听路由的变化,
注意模块导入的顺序,AppRoutingModule是最后一个,否则会被其他的拦截。
路径参数
- 配置
{path:':tabLink',component:HomeDetailComponent}
- 激活,并设置激活样式
<a [routerLink]="['/home',tab.link]" routerLinkActive="active-link">...</a>
编程式导航this.router.navigate(['home',tab.link]);
- 读取
this.route.paramsMap.subscribe(params => {...});
路由传参
this.router.navigateByUrl('/hero/' + id)
this.router.navigate(['/hero/', id])
const routes: Routes = [
{
path:'hero/:id',
component:HeroDetailComponent
}
]
子模块读取
export class HeroDetailComponent implements OnInit {
hero$: Observalbe<Hero>
constructor(private route: ActivatedRoute){}
ngOnInit(){
this.hero$ = this.route.paramMap.pipe(
switchMap(params =>{
return this.service.getHero(params.get('id'))
}))
}
}
路径对象参数
- 激活
<a [routerLink] = "['/home',tab.link,{name::'val1'}]">...</a>
编程式导航this.router.navigate(['home',tab.link,{name:'val1'}]);
- URL
- 读取
this.route.paramsMap.subscribe(params => {...});
- snapshot (当不需要Observable时的替代品)
this.selectedId = this.route.snapshot.paramMap.get('id')
查询参数(路径中?后的字典值,可以和路径参数并存)
- 配置
{path:'home',component:HomeContainerComponent}
- 激活(路径参数+查询参数)
<a [routerLink]="['/home']" [queryParams]={name:'val1'}>...</a>
- this.router.navigate(['home'],{queryParams:{name:'val1'}})
- URL
- 读取(区别于paramsMap)
this.route.queryParamsMap.subscribe(params => {...})
嵌套路由
通常一级路由是绝对路径,二级路由以下设置为相对路径
页面中可以有多个具名的router-outlet,但匿名的只能有一个
<a [routerLink]="['grand']" routerLinkActive="active" [queryParams]="{name:'zhangsan'}">
Link to grand</a>
<a [routerLink="[{outlets:{second:aux}}]"]>Link to Second</a>
<a [routerLink]="[{outlets:{popup:['second']}}]"></a>
<router-outlet></router-outlet>
<router-outlet name="second"></router-outlet>
const namedRoutes:Routes = [
{
path:'compose',
component:ComposeMessageCompoent,
outlet:'second'
}
]
const routes:Routes = [
{path:'',redirectTo:'/heroes',pathMatch:'full'},
{path:'**',component:NotFoundComponent}
]
@NgModule({
imports:[
RouterModule.forRoot(routes.concat(namedRoutes))
]
})
路由守卫
<a routerLink="./" [routerLinkActiveOptions]="{exact : true}"></a>
//相当于全部匹配patchMatcher:'full'
- CanActivate导航到某路由
ng g g router-study/auth
阻止进入到admin路由
const routes:Routes = [
{
path:'admin',
component:AdminComponent,
canActivate:[AuthGuard],
children:[
{
path:'',
children:[
{path:'crises',component:CrisesComponent},
{path:'heroes',component:HeroesComponent},
{path:'',component:DashboardComponent}
]
}
]
}
]
export class AuthGuard implements CanActivate{
canActive(
next:ActivatedRouteSnapshot,
state:RouterStateSnapshot
):boolean {
return true;
//只有返回值为true时,路由才放行
}
}
- CanActivateChild导航到某子路由
阻止进入到children
const routes:Routes = [
{
path:'admin',
component:AdminComponent,
children:[
{
path:'',
canActivate:[AuthGuard],
children:[
{path:'crises',component:CrisesComponent},
{path:'heroes',component:HeroesComponent},
{path:'',component:DashboardComponent}
]
}
]
}
]
- CanDeactivate从当前路由离开
返回true可以离开
export interface CanComponentDeactivate {
canDeactivate:()=> Observale<boolean> | promise<boolean> | boolean;
}
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactive>{
canDeactivate(component:CanComponentDeactivate){
//return component.canDeactive ? component.canDeactive() : true;
return component?.canDeactive()
}
}
- resolve守卫
保证了数据获取后再进行路由跳转,防止因数据延迟而出现的空组件情况,以此增强用户体验。
- CanLoad来处理异步导航到某特性模块的情况