您好,登錄后才能下訂單哦!
一、路由守衛
當用戶滿足一定條件才被允許進入或者離開一個路由。
路由守衛場景:
只有當用戶登錄并擁有某些權限的時候才能進入某些路由。
一個由多個表單組成的向導,例如注冊流程,用戶只有在當前路由的組件中填寫了滿足要求的信息才可以導航到下一個路由。
當用戶未執行保存操作而試圖離開當前導航時提醒用戶。
Angular提供了一些鉤子幫助控制進入或離開路由。這些鉤子就是路由守衛,可以通過這些鉤子實現上面場景。
配置路由時候用到一些屬性,path, component, outlet, children, 路由守衛也是路由屬性。
二、CanActivate
實例:只讓登錄用戶進入產品信息路由。
新建guard目錄。目錄下新建login.guard.ts。
LoginGuard類實現CanActivate接口,返回true或false,Angular根據返回值判斷請求通過或不通過。
import { CanActivate } from "@angular/router"; export class LoginGuard implements CanActivate{ canActivate(){ let loggedIn :boolean= Math.random()<0.5; if(!loggedIn){ console.log("用戶未登錄"); } return loggedIn; } }
配置product路由。先把LoginGuard加入providers,在指定路由守衛。
canActivate可以指定多個守衛,值是一個數組。
const routes: Routes = [ { path: '', redirectTo : 'home',pathMatch:'full' }, { path: 'chat', component: ChatComponent, outlet: "aux"},//輔助路由 { path: 'home', component: HomeComponent }, { path: 'product/:id', component: ProductComponent, children:[ { path: '', component : ProductDescComponent }, { path: 'seller/:id', component : SellerInfoComponent } ] ,canActivate: [LoginGuard]}, { path: '**', component: Code404Component } ];
效果:點商品詳情鏈接控制臺會提醒用戶未登錄,不能進入商品詳情路由。
三、CanDeactivate
離開時候的路由守衛。提醒用戶執行保存操作后才能離開。
在guard目錄下新建一個unsave.guard.ts的文件。
CanDeactivate接口有一個范型,指定當前組件的類型。
CanDeactivate方法第一個參數就是接口指定的范型類型的組件,根據這個要保護的組件的狀態,或者調用方法來決定用戶是否能夠離開。
import { CanDeactivate } from "@angular/router"; import { ProductComponent } from "../product/product.component"; export class UnsaveGuard implements CanDeactivate<ProductComponent>{ //第一個參數 范型類型的組件 //根據當前要保護組件 的狀態 判斷當前用戶是否能夠離開 canDeactivate(component: ProductComponent){ return window.confirm('你還沒有保存,確定要離開嗎?'); } }
配置路由,同樣先加到provider,再配置路由。
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { ProductComponent } from './product/product.component'; import { Code404Component } from './code404/code404.component'; import { ProductDescComponent } from './product-desc/product-desc.component'; import { SellerInfoComponent } from './seller-info/seller-info.component'; import { ChatComponent } from './chat/chat.component'; import { LoginGuard } from './guard/login.guard'; import { UnsaveGuard } from './guard/unsave.guard'; const routes: Routes = [ { path: '', redirectTo : 'home',pathMatch:'full' }, { path: 'chat', component: ChatComponent, outlet: "aux"},//輔助路由 { path: 'home', component: HomeComponent }, { path: 'product/:id', component: ProductComponent, children:[ { path: '', component : ProductDescComponent }, { path: 'seller/:id', component : SellerInfoComponent } ] ,canActivate: [LoginGuard], canDeactivate: [UnsaveGuard]}, { path: '**', component: Code404Component } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], providers: [LoginGuard,UnsaveGuard] }) export class AppRoutingModule { }
效果:
點ok離開當前頁面,cancel留在當前頁面。
四、Resolve守衛
http請求數據返回有延遲,導致模版無法立刻顯示。
數據返回之前模版上所有需要用插值表達式顯示某個controller的值的地方都是空的。用戶體驗不好。
resolve解決辦法:在進入路由之前去服務器讀數據,把需要的數據都讀好以后,帶著這些數據進到路由里,立刻就把數據顯示出來。
實例:
在進入商品信息路由之前,準備好商品信息再進入路由。 拿不到信息,或者拿信息出問題了,直接跳到錯誤信息頁面,或者彈出提示,就不再進入目標路由。
先在product.component.ts中聲明商品信息類型。
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { ProductComponent } from './product/product.component'; import { Code404Component } from './code404/code404.component'; import { ProductDescComponent } from './product-desc/product-desc.component'; import { SellerInfoComponent } from './seller-info/seller-info.component'; import { ChatComponent } from './chat/chat.component'; import { LoginGuard } from './guard/login.guard'; import { UnsaveGuard } from './guard/unsave.guard'; const routes: Routes = [ { path: '', redirectTo : 'home',pathMatch:'full' }, { path: 'chat', component: ChatComponent, outlet: "aux"},//輔助路由 { path: 'home', component: HomeComponent }, { path: 'product/:id', component: ProductComponent, children:[ { path: '', component : ProductDescComponent }, { path: 'seller/:id', component : SellerInfoComponent } ] ,canActivate: [LoginGuard], canDeactivate: [UnsaveGuard]}, { path: '**', component: Code404Component } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], providers: [LoginGuard,UnsaveGuard] }) export class AppRoutingModule { }
在guard目錄下新建product.resolve.ts。ProductResolve類實現了Resolve接口。
Resolve也要聲明一個范型,范型就是resolve要解析出來的數據的類型。
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from "@angular/router"; import { Injectable } from "@angular/core"; import { Observable } from "rxjs/Observable"; import { Product } from "../product/product.component"; @Injectable() export class ProductResolve implements Resolve<Product>{ constructor(private router: Router) { } resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any { let productId: number = route.params["id"]; if (productId == 2) { //正確id return new Product(1, "iPhone7"); } else { //id不是1導航回首頁 this.router.navigate(["/home"]); return undefined; } } }
路由配置:Provider里聲明,product路由里配置。
resolve是一個對象,對象里參數的名字就是想傳入的參數的名字product,用ProductResolve來解析生成。
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { ProductComponent } from './product/product.component'; import { Code404Component } from './code404/code404.component'; import { ProductDescComponent } from './product-desc/product-desc.component'; import { SellerInfoComponent } from './seller-info/seller-info.component'; import { ChatComponent } from './chat/chat.component'; import { LoginGuard } from './guard/login.guard'; import { UnsaveGuard } from './guard/unsave.guard'; import { ProductResolve } from './guard/product.resolve'; const routes: Routes = [ { path: '', redirectTo : 'home',pathMatch:'full' }, { path: 'chat', component: ChatComponent, outlet: "aux"},//輔助路由 { path: 'home', component: HomeComponent }, { path: 'product/:id', component: ProductComponent, children:[ { path: '', component : ProductDescComponent }, { path: 'seller/:id', component : SellerInfoComponent } ] , // canActivate: [LoginGuard], // canDeactivate: [UnsaveGuard], resolve:{ //resolve是一個對象 product : ProductResolve //想傳入product,product由ProductResolve生成 }}, { path: '**', component: Code404Component } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], providers: [LoginGuard,UnsaveGuard,ProductResolve] }) export class AppRoutingModule { }
修改一下product.component.ts 和模版,顯示商品id和name。
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; @Component({ selector: 'app-product', templateUrl: './product.component.html', styleUrls: ['./product.component.css'] }) export class ProductComponent implements OnInit { private productId: number; private productName: string; constructor(private routeInfo: ActivatedRoute) { } ngOnInit() { // this.routeInfo.params.subscribe((params: Params)=> this.productId=params["id"]); this.routeInfo.data.subscribe( (data:{product:Product})=>{ this.productId=data.product.id; this.productName=data.product.name; } ); } } export class Product{ constructor(public id:number, public name:string){ } }
<div class="product"> <p> 這里是商品信息組件 </p> <p> 商品id是: {{productId}} </p> <p> 商品名稱是: {{productName}} </p> <a [routerLink]="['./']">商品描述</a> <a [routerLink]="['./seller',99]">銷售員信息</a> <router-outlet></router-outlet> </div>
效果:
點商品詳情鏈接,傳入商品ID為2,在resolve守衛中是正確id,會返回一條商品數據。
點商品詳情按鈕,傳入商品ID是3,是錯誤id,會直接跳轉到主頁。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。