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對象中定義路由列表,其中,每個路由至少包含兩個參數,即path
和component
也就是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
組件的內容了
當你定義了一個事件進行跳轉的時候,例如:
<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,該參數是數組格式,也就是說,一條路由容許接收多個守衛
那麼如何編寫守衛呢?
在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守衛在是先接口的時候須要制定一個泛型(也就是須要保護的組件),算了,直接上代碼吧:
import {CanDeactivate} from "@angular/router"; import {ProductComponent} from "../product/"; export class UnsavedGuard implements CanDeactivate<ProductComponent>{ /* 須要實現一個方法 由於是須要離開,那麼這裏須要根據組件裏的某些狀態來斷定 */ canDeactivate(component:ProductComponent){ return window.confirm("您還沒保存,肯定要離開嗎?"); } }
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的學習之路仍未完待續......