路由
- Routes : 路由配置保存着那個url對應着那個組件,以及在那個routerOutlet中展示的信息
- RouterOutlet:在HTML中白哦記錄有內容呈現位置的指令
- Router: 負責在運行時執行路由的對象,可以通過調用其navigate()和navigatgeByUrl()方法來到導航到指定路由
- RouterLink:在HTML中聲明路由導航用的指令
- ActivatedRoute當前激活的路由對象,保存着當前的路由信息,如路由地址,路由參數等
- 當點擊一個導航時,就會按照路由配置,替換該路由配置所對應的插座中的內容.。
首先創建一個路由模塊
- 在routes中對路由的匹配是自上而下識別的。通配符的要放在最後
import {NgModule} from "@angular/core";
import {Routes, RouterModule} from "@angular/router";
import {HomeComponent} from "./home/home.component";
const routes: Routes = [
{path: '', component: HomeComponent},
{path: 'product/:id', component: HomeComponent},
{path:'**',component:404Compent}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: []
})
export class AppRoutingModule { }
然後將主模塊導入配置好的路由模塊:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
...
@NgModule({
imports: [
BrowserModule,
FormsModule,
AppRoutingModule//導入配置好的路由模塊
],
declarations: [
AppComponent,
HomeComponent,
HeroesComponent,
PageNotFoundComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
之後在頁面中需要一個容器來承載子模塊的內容,並導航
<h1>Angular Router</h1>
<nav>
<a routerLink="['/']" routerLinkActive="active">Home</a>
<a routerLink="['/product']" routerLinkActive="active">Heroes</a>
</nav>
<router-outlet></router-outlet>
- 在components.ts文件裏用router控制路由導航
<button (click)="myroute()"></button>
<router-outlet></router-outlet>
import { Component } from '@angular/core';
import {Router}from"@angular/router";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(private router:Router){
}
myroute(){
this.router.navigate(['/product']);
}
}
關於路由附帶參數的問題
1.
<a [routerLink]="['/product']" [queryParams]="{id:1}"></a>
2.1
{ path: 'heroes/:id', component: HeroesComponent } //模塊
<a [routerLink]="['/product',1]"></a> //html
2.2
myroute(){
this.router.navigate(['/product,2]);
}
3.
- 當路由附帶參數時,怎樣接收參數(ActivatedRoute)
import { ActivatedRoute, Params } from '@angular/router';
...
private productId:number;
export class a {
constructor(
private route: ActivatedRoute //接收
) {}
this.productId=this.route.queryParams[id];
this.productId=this.route.params[id];
}
- 小問題,當有兩個點擊導航向同一個路由時,相當於路由沒變,所以並不會刷新頁面。所以即使兩次附加的參數不同,也不會進行改變。
- 解決辦法:爲參數進行訂閱。
this.route.params.subscribe((params:Params)=>this.productId==params["id"]);
重定向路由
import {NgModule} from "@angular/core";
import {Routes, RouterModule} from "@angular/router";
import {HomeComponent} from "./home/home.component";
const routes: Routes = [
{path: '', redirectTo:'/home',pathMatch:'full'},
{path:'home',component: HomeComponent},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: []
})
export class AppRoutingModule { }
子路由
- 在子頁面裏可以無限嵌套承載容器來跳轉子路由
- 注意: 子路由導航的前提是子頁面必須有承載容器,如果沒有承載容器,就不會尋找子路由。
- 導航的子路由路徑上必須有父路徑的路徑及參數
- 組件並不知道什麼是路由,路由的導航完全由配置決定。
import {NgModule} from "@angular/core";
import {Routes, RouterModule} from "@angular/router";
import {HomeComponent} from "./home/home.component";
const routes: Routes = [
{path:'home',component: HomeComponent,
children:[
{path:'',component: asefComponent},
{path:'/self',component: selfComponent,}
]},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: []
})
export class AppRoutingModule { }
輔助路由
- 輔助路由就相當於又多了一個路由,這個路由不受其他路由的影響。
- 對輔助路由進行控制時,也可以同時對主路由進行控制
- {outlets:{primary:’home’,aux:’chart’}}
- 因爲primary是主路由,aux是輔助路由的名字,所以還可以在後邊根據需求無限附加輔助路由進行控制。
<a [routerLink]="['/product',1]"></a> //主路由
<a [routerLink]="['/product']"></a>//主路由
<a [routerLink]="[{outlets:{primary:'home',aux:'chart'}}]">開始聊天</a>
<a [routerLink]="[{outlets:{aux:''}}]">結束聊天</a>
<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>//輔助路由
const routes: Routes = [
{path:'home',component: HomeComponent},
{path:'chart',component: chartComponent},
];
路由守衛
- 新建一個guard文件來存儲各種守衛
- 在路由模塊中爲需要進行驗證判斷的路由添加相應的守衛。並在服務中寫入這些守衛。
import {NgModule} from "@angular/core";
import {Routes, RouterModule} from "@angular/router";
import {HomeComponent} from "./home/home.component";
const routes: Routes = [
{path: '', component: HomeComponent},
{path: 'product/:id', component: HomeComponent,
canActivate:[LoginGuard]
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [LoginGuard]
})
export class AppRoutingModule { }
- 當導航向一個帶有守衛的路由時,需要進行守衛驗證,當守衛驗證通過時,纔會正確的進入路由。否則進行守衛中的其他操作。
- 各種守衛
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from "@angular/router";
import {Observable} from "rxjs";
export class LoginGuard implements CanActivate {
canActivate(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot):
Observable<boolean>|Promise<boolean>|boolean {
let loggedIn:boolean = Math.random() <0.5;
if(!loggedIn){
console.log("LoginGuard:用戶未登錄"+new Date());
}
return loggedIn;
}
}
import {CanDeactivate} from "@angular/router";
import {ProductComponent} from "../product/product.component";
export class UnsavedGuard implements CanDeactivate<ProductComponent> {
canDeactivate() {
return window.confirm("你還沒有保存.確定要離開麼?");
}
}
import {Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from "@angular/router";
import {ProductComponent, Product} from "../product/product.component";
import {Injectable} from "@angular/core";
import {Observable} from "rxjs";
@Injectable()
export class ProductResolveGuard implements Resolve<Product> {
constructor(private router: Router) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Product>|Promise<Product>|Product{
let productId:number = route.params['id'];
if(productId == 1) {
return new Product(1,'mignzi');
}else{
this.router.navigate(['/home']);
return undefined;
}
}
}