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


  }

}

發佈了28 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章