路由:根据不同地址加载不同组件,实现单页面应用
# 1 路由基础知识 =================
在angular中主要提供了下面5个对象来处理应用中路由相关的功能:
Routes: 路由配置,保存着哪个URL对应展示哪个组件,以及在哪个RouterOutlet中展示组件
RouterOutlet:在Html中标记路由内容呈现位置的占位符指令
Router: 【控制器中】负责在运行时执行路由的对象,可以通过调用其navigate()和navigateByUrl()方法来导航到一个指定的路由
RouterLink: 【html模板中a】在Html中声明路由导航用的指令
ActivatedRoute:当前激活的路由对象,保存着当前路由的信息,如路由地址,路由参数等
ng new router --routing 创建路由项目
Q1:Routes
当我们使用routing参数生成项目时
在app目录下会多生成一个app-routing.module.ts 描述当前应用的路由配置
主模块app-module.ts中元数据imports中会导入新生成的AppRoutingModule
ng g component home
ng g component product
ng g component code404
生成主页 产品 404组件
路由配置:
《app-routing.module.ts》:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {HomeComponent} from "./home/home.component";
import {ProductComponent} from "./product/product.component";
import {Code404Component} from "./code404/code404.component";
const routes:Routes = [ //注:path不能用\开头
{path: '',component: HomeComponent},
{path: 'product',component: ProductComponent},
{path:'**',component:Code404Component} //放在路由配置的最后面
];
@NgModule({
imports: [ RouterModule.forRoot(appRoutes) ],
exports: [ RouterModule ],
providers: []
})
export class AppRoutingModule { } //暴露模块
《app.module.ts》:
import { AppRoutingModule } from './app-routing.module';
... ...
imports: [
BrowserModule,
AppRoutingModule //注册路由模块
]
Q2:RouterOutlet
当我们使用routing参数生成项目时 app.component.html中会生成插座指示当前导航到某个路由的时候对应组件显示的位置[插座后面]
Q3:RouterLink
《app.component.html》:
<a [routerLink]="['/]" routerLinkActive="active">主页</a>
<a [routerLink]> = "['/product']">商品详情</a>
<router-outlet></router-outlet>
【routerkinkactive:选中路由加载的class】
.active{ color: red; } // 配置选中的样式
说明:routerLink的参数是一个数组:有时需要在路由的时候传递一些参数,需要在数组中写参数的值
Q4:Router -- js跳转
《app.component.ts》:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(private router:Router) { }
toProductDetails() {
this.router.navigate(['/product'])
// this.router.navigate(['/product' , 2])
}
}
Q5:ActivatedRoute
# 2 路由时传递数据 ===============
E1 : 在查询参数中传递数据:
/product?id=1&name=2 => ActivatedRoute.queryParams[id]
E2 : 在路由路径中传递数据:
{path:/product/:id} => /product/1 => ActivatedRoute.params[id]
E3 : 在路由配置中传递数据:
{path:/product,component:ProductComponent, data[{isProd:true}]} => ActivatedRoute.data[0][isProd]
导航到商品详情页的时候需要传商品id给商品详情组件:
E1:
《app.component.html》:【传】
<a [routerLink] = "['/']">主页</a>
<a [routerLink] = "['/product']" [queryParams] = "{id:1}">商品详情</a>
<input type="button" value="商品详情" (click)="toProductDetails()">
<router-outlet></router-outlet>
《product.component.ts》:【接】
import { Component ,OnInit} from '@angular/core';
import {ActivatedRoute} from "@angular/router";
@Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
private productId:number;
constructor(private routeInfo: ActivateRoute) { }
ngOnInit() {
this.productId = this.routeInfo.snapshot.queryParams["id"];
}
}
《product.component.html》:
<p>商品ID是:{{productId}}</p>
E2:
《app-routing.module.ts》:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {HomeComponent} from "./home/home.component";
import {ProductComponent} from "./product/product.component";
import {Code404Component} from "./code404/code404.component";
const routes:Routes = [
{path: '',component: HomeComponent},
{path: 'product/:id',component: ProductComponent},
{path:'**',component:Code404Component}
];
@NgModule({ imports: [ RouterModule.forRoot(appRoutes) ], exports: [ RouterModule ], providers: [] })
export class AppRoutingModule { }
《app.component.html》:
<a [routerLink] = "['/']">主页</a>
<a [routerLink] = "['/product' , 1]">商品详情</a>
<input type="button" value="商品详情" (click)="toProductDetails()">
<router-outlet></router-outlet>
《product.component.ts》:
import { Component ,OnInit} from '@angular/core';
import {ActivatedRoute} from "@angular/router";
@Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
private productId:number;
constructor(private routeInfo: ActivateRoute) { }
ngOnInit() {
this.routeInfo.params.subscribe((params:Params) => this.productId = params ["id"]);
}
}
从组件A 路由到组件B时,B组件会被创建,它的constructor方法会被调用,它的ngOnInit方法会被调用一次
但是如果从组件B到组件B ,ngOnInit方法不会再次创建,所以productId属性保持着第一次创建时赋予的值
解决方案:
** 参数订阅
this.routeInfo.params.subscribe((params:Params) => this.productId = params ["id"]): + subscribe 订阅
+ Params 类型
+ 订阅之后声明一个匿名函数来处理传进的参数params, 从参数中取出id赋给本地的productId
** 参数快照:
ngOnInit() { this.productId = this.routeInfo.snapshot.queryParams["id"]; }
小结:如果确定不会由组件A 路由到组件A 可使用参数快照,反之,使用参数订阅