1. 程式人生 > >angular4基礎之路由

angular4基礎之路由

路由

  • 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;
    }


  }

}