Angular4.0從入門到實戰打造在線競拍網站學習筆記之二--路由

Angular4.0基礎知識之組件
Angular4.0基礎知識之路由
Angular4.0依賴注入
Angular4.0數據綁定&管道html

路由

簡介

接下來學習路由的相關知識typescript

原本是不許備寫下去的,由於當時看視頻學的時候感受本身掌握的不錯 ( 這是一個灰常很差的想法 ) ,過了一段時間才發現Angular這個對我這個PHP程序猿來講不太經常使用的東西很是容易忘!幸虧以前去寫了筆記。數組

首先須要先了解一個概念(SPA),也就是單頁面應用,一個頁面只加載一次,再也不刷新,只改變頁面部份內容的應用。app

路由的做用就是爲每個視圖分配一個惟一的URL,進入這個URL的時候,使應用跳到某個特定的視圖狀態。dom

建立

在建立項目的時候 , 帶上參數ng new RouterDemo --routing便可生成一個帶路由文件的項目ide

Angular路由常見對象函數

名稱 簡介
Routes 路由的配置,URL和組件之間的映射以及組件和組件插座RouterOutlet的映射關係
RouterOutlet 在HTML中標記組件插入位置的佔位符標籤
Router 在運行時執行路由的對象,navigate()navigateByUrl()方法導航到指定的路由,使用依賴注入在控制器中獲取
RouterLink 在HTML中聲明路由導航的標籤屬性
ActivatedRoute 當前激活的路由對象,保存着當前路由的信息,如路由地址參數等,使用依賴注入在控制器中獲取

在項目中,路由文件一般爲app-routing.module.ts學習

配置

打開路由文件,在routes:Routes對象中定義路由列表,其中,每個路由至少包含兩個參數,即pathcomponent也就是URL和組件的映射關係this

注意:這裏的path最好不要以/開頭,不然會致使路由URL相對關係的混亂,Angular會自動幫你處理和子路由的關係,除非你明確知道你要作什麼code

app-routing.module.ts源碼

import {NgModule} from '@angular/core'
import {RouterModule, Routes} from '@angular/router';
import {ProductDetailComponent} from './product-detail/product-detail.component';
import {HomeComponent} from './home/home.component';

const routes: Routes = [
    {path: '', component: HomeComponent},
    {path: 'product/:prodTitle', component: ProductDetailComponent}
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule],
    providers: []
})

export class AppRoutingModule {}

app.module.ts修改部分

imports: [
        ...
        AppRoutingModule
        ...     
    ],

如上,最簡單的路由便定義完畢啦

插座

所謂的插座,也就是在HTML中定義的路由對應的組件插入點

使用<router-outlet></router-outlet>標籤訂義路由對應組件的插入位置(在該標籤下面)

路由連接

使用<a [routerLink]=['/product']>商品詳情</a>來定義一個路由導航連接

注意這裏的路由字符串須要加上/,後面咱們會使用./等來區分路由和子路由
路由的參數是一個數組而不是字符串,由於後面咱們須要給路由傳遞參數

而後咱們就能夠經過點擊商品詳情連接來顯示product組件的內容了

使用Router對象進行導航

當你定義了一個事件進行跳轉的時候,例如:

<input type="button" (click)="toProductInfo()" />

控制器代碼

export class AppComponent {
    // 使用依賴注入拿到Router對象
    constructor(private router:Router){}
    // 事件綁定的方法,跳轉
    toProductInfo() {
        this.router.navigate(['/product']);
    }
}

便可實現用代碼進行路由跳轉

默認路由

當輸入一個不存在的地址時,路由插座區域沒法顯示,而且會在控制檯拋出異常,咱們能夠經過定義一個默認路由(例如404page)來避免錯誤發生

首先,咱們生成一個新的組件,運行ng g component code404

生成404頁面組件,簡單編寫內容以後,進入路由配置文件,添加一個新的路由配置信息

...
// 放在最後,當匹配不到的時候會選擇此路由
{path:'**',component:Code404Component}

傳遞參數

傳遞

傳遞方式 形式 獲取方式
查詢參數傳遞(GET方法) <a [routerLink]=['/product'] [queryParams]="{id:1}"></a>=>/?id=1&name=jeffrey ActivatedRoute.queryParams['id']
在路由形式中定義參數 {path:'product/:id'}=><a [routerLink]=['/product/',1]></a>=>/product/1 ActivatedRoute.params['id']
在路由配置中定義靜態數據 {{path:'product/:id',component:ProductComponent,data:[{osProd:true}]}} ActivatedRoute.data[0]['isProd']

獲取

在constructor構造函數參數中使用依賴注入獲取到ActivatedRoute存入routeInfo變量,在ngOnInit()取出參數

  • 直接取出(參數快照)
    this.productId=this.routeInfo.snapshort.queryParams['id']
  • 關聯獲取(參數訂閱),在同翼哥組件之間路由的時候,因爲ngOnInit()只會執行一次,致使參數不能刷新,這時候可使用參數訂閱來關聯地獲取到參數。(下面例子使用了箭頭函數)
    this.routeInfo.params.subscribe((params:Params)=>this.productId=params['id'])

重定向路由

在訪問一個特定路由時,重定向到另外一個指定地址

例如:

{path: '', redirectTo:'/home',pathMatch:'full'},
{path: 'home', component: HomeComponent},

pathMatch指匹配策略

當咱們訪問http://127.0.0.1:4200的時候,會自動跳轉到http://127.0.0.1:4200/home

子路由

在一個路由的組件中展現其餘組件的內容時,使用子路由來實現。

其實更應該理解爲「子組件」,也就是一個大的組件裏的一部分,使用子路由來控制

在主路由的routerOutlet顯示主路由的組件內容時,根據子路由的變化,在主路由組件中子路由對應routerOutlet位置顯示對應的子路由組件

輔助路由

形式:<router-outlet name="fuzhu"></router-outlet>

{path:'xxx',component:XxxComponent,outlet:'fuzhu'}

<a [routerLink]=['/home',{outlets:{fuzhu:'xxx'}}]>連接</a><a [routerLink]=[{outlets:{primary:'home',fuzhu:'xxx'}}]>連接</a>

當點擊連接的時候,主插座會顯示home組件的內容,fuzhu插座會顯示xxx路由匹配到的Xxx組件

<a [routerLink]=[{outlets:{fuzhu:'xxx'}}]>連接</a>

當點擊連接的時候,主插座不變,fuzhu插座會顯示xxx路由匹配到的Xxx組件

<a [routerLink]=[{outlets:{fuzhu:null}}]>連接</a>

當點擊連接的時候,fuzhu插座不顯示任何組件

輔助路由容許你在同一個組件中定義多個插座,並定義每一個插座顯示的內容

路由守衛

簡介

所謂的路由守衛,也就是在知足必定條件的時候才容許進入或退出某一個路由。例如:

  • 在用戶登陸以前,不容許進入我的中心頁面
  • 在某個表單的執行流程中,只有用戶完成了上一步的任務以後,才能進入下一步的環節
  • 當用戶沒有執行保存操做而試圖離開某一個路由的時候,阻止離開並進行提示

路由守衛主要有三種類型:

  • CanActivate 是否能進入到某個路由
  • CanDeactivate 是否能離開某個路由
  • Resolve 在路由激活以前獲取數據

如今,在路由對象裏咱們有多了一個新的參數:canActivate,該參數是數組格式,也就是說,一條路由容許接收多個守衛

那麼如何編寫守衛呢?

canActivate守衛

src目錄中創建一個存放守衛的目錄guard,新建路由守衛TypeScript文件,例如login.guard.ts,下面展現一個簡單的Demo:

(爲了便於演示,不去作真正的登陸服務,只是生成一個隨機數來判斷是否已經登陸)

import {canActivate} from "@angular/router";

export class LoginGuard implements CanActivate {
    canActivate(){
        // 假設隨機數小於0.5就表明已經登陸
        let isLogin:boolean = Math.random()<0.5;

        if(!isLogin){
            console.log("未登陸");
        }

        return isLogin;
    }
}
import {LoginGuard} from "./guard/login.guard";

{path:'product/:id',component:ProductComponent,children:[......],canActivate:[LoginGuard]}

...

@NgModule({
    imports:[...],
    exports:[...],
    providers:[LoginGuard]
})

這樣,咱們就是先了一個簡單的路由守衛,當咱們試圖導航到這個路由的時候,會判斷守衛返回的Boolean值,爲True則經過。

!還有這種操做?!在學Angular的時候順便學了TypeScript~

canDeactivate守衛

同理,咱們能很輕易地區是先一個canDeactivate守衛,區別在於canDeactivate守衛在是先接口的時候須要制定一個泛型(也就是須要保護的組件),算了,直接上代碼吧:

import {CanDeactivate} from "@angular/router";
import {ProductComponent} from "../product/";

export class UnsavedGuard implements CanDeactivate<ProductComponent>{
    /*
    須要實現一個方法
    由於是須要離開,那麼這裏須要根據組件裏的某些狀態來斷定
    */
    canDeactivate(component:ProductComponent){
        return window.confirm("您還沒保存,肯定要離開嗎?");
    }
}

Resolve守衛

Resolve守衛經常使用於解決數據預加載問題,若是使用路由中傳遞的參數,在進入某一個組件以後發出Http請求去獲取所須要的數據,那麼在剛進入這個組件的時候,全部使用插值表達式的位置都是空的,這樣用戶體驗會不好。這時候可使用Resolve守衛來解決,在進入以前先獲取數據,進入以後當即使用並顯示出來

import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
import {Product} from '../product/product.component';
import {Observable} from 'rxjs/Observable';
import {Injectable} from '@angular/core';

@Injectable() // 裝飾器,容許注入
export class ProductResolve implements Resolve<Product> {
  // 注入路由對象
  constructor(private router: Router) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Product | Observable<Product> | Promise<Product> {
    const productId: number = route.params['id'];
    if (productId === 1) {
      return new Product(1, '小米6', 2999, 5, '很不錯的手機', ['數碼'])
    } else {
      this.router.navigate(['/home']);
      return undefined;
    }
  }

}

在路由中咱們有遇到了一個新的參數:resolve,接收一個數組(Resolve守衛)

{path:'product/:id',component:ProductComponent,resolve:{product:ProductResolve}}

一樣須要在providers裏聲明一下。

那麼如何取出Resolve守衛傳入的數據呢?

一樣可使用參數訂閱的方式:

// routeInfo:ActivatedRoute
this.routeInfo.data.subscribe((data:{product:Product})=>{
    this.productId=data.product.id;
});

好了,路由的知識點到如今就告一段落,可是Angular的學習之路仍未完待續......

相關文章
相關標籤/搜索