跳到主要内容

路由

一、Angular中的路由

在创建项目的时候使用--routing参数可以使得项目自带路由模块。

ng new angularRouter --routing

生成的项目中有一个app-routing.module.ts 文件就是路由配置文件。

为了测试方便,创建Home和Goods,Detail页面:

ng g c pages/Home
ng g c pages/Goods
ng g c pages/Detail

路由配置:

import { HomeComponent } from './pages/home/home.component';
import { GoodsComponent } from './pages/goods/goods.component';
import { DetailComponent } from './pages/detail/detail.component';

const routes: Routes = [
{
path: '',
redirectTo: '/home',
pathMatch: 'full'
},
{
path: 'home',
component: HomeComponent,
children : [
{
path : "a",
component : AComponent
}
]
},
{
path: 'goods',
component: GoodsComponent
},
{
path: 'detail',
component: DetailComponent
},
// 路由不存在时匹配
{
path: '**',
component: PageNotFoundComponent
}
];

注意:

1、路径不加 /

2、路由不存在时匹配** 跳转到404页面。

3、重定位redirectTo: '/home',

4、pathmatch中的“full”,代表的是当path中是空时,redirectTo会转向主页的路径上

二、路由跳转

1、标签跳转

在主组件中点击a标签跳转到Home组件和Goods组件。

<!-- app.component.html -->

<a [routerLink]="[ '/' ]">首页</a>
<a [routerLink]="[ '/goods' ]">商品详情页</a>

路由跳转:[routerLink]="[ '/' ]

第一个[]表示routerLink是可变的,路由也是数组,是为了在数组的第二个参数添加参数,比如跳转到详情页需要传入商品id。

2、编程式导航

在控制器(ts文件的类中)中,通过js跳转需要进行两步:

第一步: 在构造函数中声明 Router实例

例如: constructor(private xxx:Router){}

第二部 调用Router实例的navigate()方法即可(注意,该方法接收的参数为数组类型)

例如: this.xxx.navigate(["/home"]) 跳转到首页

示例:

/*app.component.html*/
<button (click)="goPage('/')">首页</button>
<button (click)="goPage('/goods')">商品列表</button>

/*app.component.ts*/
import { Router } from "@angular/router";
constructor(private router: Router) { } // 注意导入Router

goPage(path) {
this.router.navigate([path]); // 是个数组
}

三、路由传参

1、问号传参

goods页点击商品跳转到detail页面,商品id由地址栏传递:

<!-- goods.component.html -->
<div>
<ul>
<li
*ngFor="let goods of list"
[routerLink]="[ '/detail']"
[queryParams]="{goodsID:goods.id}"
>
<p>商品名:{{goods.name}}</p>
<p>价格:{{goods.price}}</p>
</li>
</ul>

</div>

给元素添加属性 queryParams即可传递想要的数据

详情页detail从地址栏获取id:

import { ActivatedRoute } from '@angular/router';

export class DetailComponent implements OnInit {
constructor(
private ar: ActivatedRoute
) { }

ngOnInit() {
let id = this.ar.snapshot.queryParams['goodsID'];
console.log(id);
}
}

给当前组件注入 ActivatedRoute,通过注入的服务实例来获取参数

注意:直接打印 this.ar.snapshot.queryParams 是一个对象,但是只能使用数组的方式获取。

2、路径传参

首先需要修改路由配置:

{
path: 'detail/:goodsID',
component: DetailComponent
}
<!-- goods.component.html -->

<div>
<ul>
<li
*ngFor="let goods of list"
[routerLink]="[ '/detail', goods.id]">
<p>商品名:{{goods.name}}</p>
<p>价格:{{goods.price}}</p>
</li>
</ul>
</div>

参数通过routerLink属性值的数组第二个元素进行传参

详情页获取id:

import { ActivatedRoute } from '@angular/router';

export class DetailComponent implements OnInit {
constructor(
private ar: ActivatedRoute
) { }

ngOnInit() {
let id = this.ar.snapshot.params['goodsID'];
console.log(id);
}
}

获取的方式和问号传参唯一的区别:

需要通过 this.xxx.snapshot.params['goodsID']来获取数据。

当从详情页跳转到详情页的时候,由于详情页组件没有进行组件的卸载和加载,所以不能使用上面参数快照的方式进行,而需要采用参数订阅的方式:

ngOnInit() {
// let id = this.ar.snapshot.params['goodsID'];
this.ar.params.subscribe(params => {
console.log(params['goodsID']);
})
}

四、辅助路由(多视图路由)

与vue等框架的区别在于,angular的对视图路由互相是独立的,A视图更换路由不会改变B视图的显示,反之亦然。

在主组件的html设置显示主路由和辅助路由。

<!--app.component.html-->


<button (click)="goPage('/home')">首页</button>
<button (click)="goPage('/goods')">商品列表</button>

<a [routerLink]="[ {outlets:{box:'a'}} ]">辅助路由 1</a>
<a [routerLink]="[ {outlets:{box:'b'}} ]">辅助路由 2</a>

<div class="panel">
<div class="main">
<router-outlet></router-outlet>
</div>
<div class="box">
<router-outlet name="box"></router-outlet>
</div>
</div>

辅助路由定义一个name属性box。

修改路由:

import { AComponent } from './components/a/a.component';
import { BComponent } from './components/b/b.component';

const routes: Routes = [
//...
{
path: 'a',
component: AComponent,
outlet: 'box'
},
{
path: 'b',
component: BComponent,
outlet: 'box'
},
//...
];

注意属性 outlet: 'box' 表示组件渲染的是名字为box的路由。

然后点击a标签进行辅助路由跳转:

<a [routerLink]="[ {outlets:{box:'a'}} ]">辅助路由 1</a>
<a [routerLink]="[ {outlets:{box:'b'}} ]">辅助路由 2</a>

当点击a标签的时候,将box替换为a组件或者b组件。

可以看到:当点击主路由时不影响辅助路由的跳转,点击辅助路由时不影响主路由的跳转。并且辅助路由会以括号的形式显示在地址栏上。

五、路由守卫

常见的由进入的路由守卫和离开的路由守卫。本质上来说,路由守卫就是类。

在guards目录下新建一个进入路由守卫和一个离开路由守卫。路由守卫其实就是一个类,所以:

ng g cl guards/Enter
ng g cl guards/Leave

1、编写进入守卫模块

import { CanActivate } from "@angular/router";

export class Enter implements CanActivate {
canActivate(): boolean {
// 返回true运行跳转,返回false禁止跳转
return confirm('确认进入?');
}
}

进入的路由守卫需要实现接口: CanActivate

2、将其注入到路由模块的providers属性中

providers: [Enter]

3、在需要监控的路由配置上添加对应的路由守卫。

{
path: 'home',
component: HomeComponent,
canActivate: [Enter]
},
{
path: 'goods',
component: GoodsComponent,
canActivate: [Enter]
},

如果有多个路由守卫的话,路由守卫会依次验证。

离开守卫:

离开的路由守卫需要实现接口 :CanDeactivate (除了要实现接口,还得定义泛型),其他都是相同的。

import { CanDeactivate } from "@angular/router";
import { GoodsComponent } from "app/pages/goods/goods.component";

export class Leave implements CanDeactivate<GoodsComponent> {
canDeactivate(): boolean {
return confirm("你确定要离开吗?")
}
}

注意:进入守卫和离开守卫的区别:

离开守卫除了要实现接口,还得定义泛型。

注入:

providers: [Enter,Leave]

添加相应的路由守卫:

{
path: 'home',
component: HomeComponent,
canActivate: [Enter],
canDeactivate: [Leave]
},
{
path: 'goods',
component: GoodsComponent,
canActivate: [Enter],
canDeactivate: [Leave]
},