1. a 链接的 routerLink 属性展示对应的子组件内容。
命令 ng new routeDemo --routing 新建一个具有路由功能的项目。
在app.module 中配置
path 路径不能 / 开头, 方便多页面导航用到相对路径和绝对路径。
路由根据匹配优先按照顺序来匹配,可在最后添加一个通配符的路由匹配。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import {HomeComponent} from "./home/home.component";
import {DetailComponent} from "./detail/detail.component";
// 根路由:
const routes: Routes = [
{path:'',component: HomeComponent},
{path:'product',component: DetailComponent}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
在html 中 路径 / 开头,表示导航到一个根路由。app.html 在 router-outlet 显示展示的内容。
routeLink 用于导航带一个url 地址。参数时一个数组,后面可以跟一些要传的参数。
<a [routerLink]="['/product']" >商品详情</a>
<a [routerLink]="['']" ></a>主页
<router-outlet></router-outlet>
2. 传递参数
2.1查询参数 传参写在queryParams 中 http://localhost:4200/product?id=1
<a [routerLink]="['/product']" [queryParams]="{id:1}" >商品详情</a>
在对应的商品组件中的 product.compoent.ts 方法接收传递的值。
2.Router对象的 navigate 方法跳转
根据 angular 数据绑定之事件绑定。
3.ActivedRoute来匹配
ActivedRoute.param[id] 得到参数值
import { Component, OnInit } from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router";
@Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css']
})
export class DetailComponent implements OnInit {
private productId:number;
constructor(private route:ActivatedRoute) {
}
ngOnInit() {
this.productId=this.route.snapshot.queryParams["id"];
}
}
snapshot (快照)方法导致若之前请求过此路径,用snapshot 请求时将得到的是原来的值。
这是由于在创建组件后不会被再次创建 ,ngOnit() 方法创建一次,productId 保持第一次创建时的值。
解决方法: 参数订阅
声明一个匿名的函数来处理传进入的参数。
ngOnInit() {
this.route.params.subscribe((params:Params) => this.productId=params["id"]);
}
2.2 从url 中取 app-routing 设置。
const routes: Routes = [
{path:'',component: HomeComponent},
{path:'product/:id',component: DetailComponent}
];
<a [routerLink]="['/product',1]" >商品详情</a>
3.重定向路由 redirectTo:
const routes: Routes = [
{path:'',redirectTo:'home',pathMatch:'full'},
{path:'home',component: HomeComponent},
{path:'product/:id',component: DetailComponent}
];
4. 子路由配置
const routes: Routes = [
{path:'',redirectTo:'home',pathMatch:'full'},
{path:'home',component: HomeComponent},
{path:'product/:id',component: DetailComponent,children:[{path:'',component:ProductDetailComponent},{
path:'seller/:id',component:SellerComponent
}]
}
];
import {ActivatedRoute, Params} from "@angular/router";
@Component({
selector: 'app-seller',
templateUrl: './seller.component.html',
styleUrls: ['./seller.component.css']
})
export class SellerComponent implements OnInit {
private sellerId:number;
constructor(private route:ActivatedRoute) { }
ngOnInit() {
this.route.params.subscribe((params: Params) => this.sellerId=params["id"]);
}
}
5. 辅助路由
声明辅助路由在主路由的旁边。name属性。 这些都需要在route 中标明。
在a 链接中定义跳转到 chat 路径的对象 [outlets : {aux: chat}],可添加primary 主路由,表示当跳转到辅助路由时,对应的主路由是什么。
const routes: Routes = [
{path:'',redirectTo:'home',pathMatch:'full'},
{path:'chat',component: ChatComponent,outlet:'aux'},
{path:'home',component: HomeComponent},
{path:'product/:id',component: DetailComponent,children:[{path:'',component:ProductDetailComponent},{
path:'seller/:id',component:SellerComponent
}]
},
];
<div class="pro">
<h1>
Welcome to {{title}}!
</h1>
<a [routerLink]="['/product',1]" >商品详情</a>
<a [routerLink]="['/home']" >主页</a>
<a [routerLink]="[{outlets: {primary: 'home',aux: 'chat'}}]">开始聊天</a>
<a [routerLink]="[{outlets: {aux: null}}]">结束聊天</a>
<input type="button" value="商品详情" (click)="toDetail()" >
<router-outlet></router-outlet>
</div>
<router-outlet name="aux"></router-outlet>
6. 路由守卫
用于一些权限控制,进入某页面激活,退出某页面等。
定义一个类,继承 CanActivate 实现 canActivate 方法,返回true 时,通过。false 不通过。
import {CanActivate} from "@angular/router"; export class LoginGuard implements CanActivate{ canActivate() { let login= Math.random()<0.5; if (login){ console.log('请登录'); } console.log(Math.random()<0.5); return !login; } }
在路由中配置,即加在想要拦截的路径后面。
const routes: Routes = [ {path:'',redirectTo:'home',pathMatch:'full'}, {path:'chat',component: ChatComponent,outlet:'aux'}, {path:'home',component: HomeComponent}, {path:'product/:id',component: DetailComponent,children:[{path:'',component:ProductDetailComponent},{ path:'seller/:id',component:SellerComponent }],canActivate:[LoginGuard],canDeactivate:[LoginOutGuard] }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], providers:[LoginGuard,LoginOutGuard] }) export class AppRoutingModule { }
canDeactive 为退出时拦截,当点击确认退出时,返回 true.
import {CanDeactivate} from "@angular/router"; import {ProductDetailComponent} from "../product-detail/product-detail.component"; export class LoginOutGuard implements CanDeactivate<ProductDetailComponent>{ canDeactivate(component: ProductDetailComponent) { return window.confirm("确定要退出商品详情页面吗"); } }
7. resolve 守卫解决显示延迟导致显示为空的情况。(进入组件之前拿到数据,若拿不到数据,则跳转到相关组件)
resolve 守卫首先去服务器上抓取信息,然后返回抓取的信息。
定义一个类ProductResolve 实现 Resolve<T>类,重写resolve 方法(route : ActivatedRouteSnapShot 参数)
//ActivatedRouteSnapShot =this.router.snapshot
定义类的上方需要用一个注解注入(由构造函数注入)。component 不需要注入是由于 component 注解已经继承了@injectable() 装饰器
ProductResolve 解析 product.product 为传入的参数名字。
resolve: { product : ProductResolve}
若不加注解注入。会报如下错误:
client:139 C:/Users/SAMSUNG/Desktop/routeDemo/routeDemo/src/app/guard/productResolve.guard.ts (7,18): Cannot find name 'ActivatedRouteSnapshot'.
client:139 C:/Users/SAMSUNG/Desktop/routeDemo/routeDemo/src/app/guard/productResolve.guard.ts (7,49): Cannot find name 'RouterStateSnapshot'.
client:139 C:/Users/SAMSUNG/Desktop/routeDemo/routeDemo/src/app/guard/productResolve.guard.ts (7,71): Cannot find name 'Observable'.
client:139 C:/Users/SAMSUNG/Desktop/routeDemo/routeDemo/src/app/guard/productResolve.guard.ts (10,14): Supplied parameters do not match any signature of call target.
import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from "@angular/router"; import {Observable} from "rxjs"; import {Product} from "../product-detail/product-detail.component"; import {Injectable} from "@angular/core"; // @ts-ignore @Injectable() export class ProductResolveGuard implements Resolve<Product>{ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Product> | Promise<Product> | Product { let id: number = route.params["id"]; if (id == 1) { return new Product(1, "metu"); } return undefined; }
const routes: Routes = [ {path:'',redirectTo:'home',pathMatch:'full'}, {path:'chat',component: ChatComponent,outlet:'aux'}, {path:'home',component: HomeComponent}, {path:'product/:id',component: DetailComponent,children:[{path:'',component:ProductDetailComponent},{ path:'seller/:id',component:SellerComponent }],canActivate:[LoginGuard],canDeactivate:[LoginOutGuard],resolve: {product: ProductResolveGuard} }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], providers:[LoginGuard,LoginOutGuard,ProductResolveGuard] }) export class AppRoutingModule { }