angular4基礎之路由
阿新 • • 發佈:2019-01-31
路由
- 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 { }
之後在頁面中需要一個容器來承載子模組的內容,並導航
- 在html頁面中用routerLink控制導航
<!--HTML頁面-->
<h1>Angular Router</h1>
<nav>
<!--這裡的路由用的是陣列,可以傳遞一些引數-->
<a routerLink="['/']" routerLinkActive="active">Home</a>
<!--routerLink指令就是給a標籤新增一個跳轉導航。點選之後會導航向對應路由,並獲取對應路由的內容,放入下邊的容器-->
<!--routerLinkActive定義該路由啟用時的樣式類。-->
<a routerLink="['/product']" routerLinkActive="active">Heroes</a>
</nav>
<router-outlet></router-outlet><!--承載容器,點選上邊兩個之後所顯示的內容會放在這裡-->
- 在components.ts檔案裡用router控制路由導航
<!--html檔案-->
<!--點選之後呼叫muroute方法-->
<button (click)="myroute()"></button>
<router-outlet></router-outlet><!--承載容器,點選上邊按鈕之後所顯示的內容會放在這裡-->
<!--components.ts檔案-->
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方法被html頁面點選呼叫-->
myroute(){
this.router.navigate(['/product']);<!--路由導航-->
}
}
關於路由附帶引數的問題
- 路由跳轉時怎樣附帶引數
1.
<!--在查詢引數中傳遞資料 直接附加在html上的routerlink上邊-->
<a [routerLink]="['/product']" [queryParams]="{id:1}"></a>
2.1
<!--在路由路徑中傳遞資料 在模組中附加引數,html中直接附加資料-->
{ 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]; //對應第一個在查詢引數中傳遞資料 /product?id=1&name=2
this.productId=this.route.params[id];//對應第二個在路由路徑中傳遞資料{ path: 'heroes/:id', component: HeroesComponent }
}
- 小問題,當有兩個點選導航向同一個路由時,相當於路由沒變,所以並不會重新整理頁面。所以即使兩次附加的引數不同,也不會進行改變。
- 解決辦法:為引數進行訂閱。
<!--訂閱-->
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'},//當訪問空連結時,會跳轉向home路由
{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是輔助路由的名字,所以還可以在後邊根據需求無限附加輔助路由進行控制。
<!--HTML-->
<a [routerLink]="['/product',1]"></a> //主路由
<a [routerLink]="['/product']"></a>//主路由
<!--當點選開始聊天時,他會時這個輔助路由導航向聊天頁面,同時是主路由導航向home頁面,當點選結束聊天時,輔助路由為空,所以內容也會消失為空。-->
<!--{outlets:{aux:''}}這個是輔助路由,aux是輔助路由的名字。可以有多個輔助路由。後邊是路徑-->
<!--{outlets:{primary:'home',aux:'chart'}} primary是主路由,在控制輔助路由時也可以控制住路由的導航,根據需求可寫可不寫-->
<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 { }
- 當導航向一個帶有守衛的路由時,需要進行守衛驗證,當守衛驗證通過時,才會正確的進入路由。否則進行守衛中的其他操作。
- 各種守衛
//驗證守衛 CanActivate 判斷各種資料是否匹配
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from "@angular/router";
import {Observable} from "rxjs";
/**
* Created by zhailiang on 2017/1/23.
*/
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;//根據不同結果導航進不同介面或給予提示
}
}
//驗證是否儲存的守衛 也就是離開這個路由時的驗證
//CanDeactivate<ProductComponent>這裡時傳入現在所在的頁面元件
import {CanDeactivate} from "@angular/router";
import {ProductComponent} from "../product/product.component";
/**
* Created by zhailiang on 2017/1/23.
*/
export class UnsavedGuard implements CanDeactivate<ProductComponent> {//泛型,指定當前元件也就是現在所在的頁面元件,為了保護元件
//當離開這個路由時給予下面的提示,如果點選取消則還會保留在本頁面。
canDeactivate() {
return window.confirm("你還沒有儲存.確定要離開麼?");
}
}
//Resolve守衛 也就是當導航向一個路由時,會驗證引數,如果匹配則獲取這些資料,並導航向正確路由,同時將資料放入頁面中,如果不匹配則導航向其他路由。
import {Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from "@angular/router";
import {ProductComponent, Product} from "../product/product.component";
import {Injectable} from "@angular/core";
import {Observable} from "rxjs";
/**
* Created by zhailiang on 2017/1/23.
*/
@Injectable()
export class ProductResolveGuard implements Resolve<Product> {// 同樣是泛型,這裡是要解析出來的資料型別 這個資料型別要進行宣告,也就是定義
constructor(private router: Router) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Product>|Promise<Product>|Product{
//這的route就是productComponent裡的this.ActivatedRoute
let productId:number = route.params['id'];//獲取路由引數
if(productId == 1) {
return new Product(1,'mignzi');//如果驗證通過就從後臺獲取資料並返回進導航的路由
}else{
this.router.navigate(['/home']);//如果不通過則跳轉路由進入首頁
return undefined;
}
}
}