Angular路由——路由守衛
一、路由守衛
當使用者滿足一定條件才被允許進入或者離開一個路由。
路由守衛場景:
只有當使用者登入並擁有某些許可權的時候才能進入某些路由。
一個由多個表單組成的嚮導,例如註冊流程,使用者只有在當前路由的元件中填寫了滿足要求的資訊才可以導航到下一個路由。
當使用者未執行儲存操作而試圖離開當前導航時提醒使用者。
Angular提供了一些鉤子幫助控制進入或離開路由。這些鉤子就是路由守衛,可以透過這些鉤子實現上面場景。
CanActivate: 處理導航到某路由的情況。
CanDeactivate: 處理從當前路由離開的情況。
Resolve: 在路由啟用之前獲取路由資料。
配置路由時候用到一些屬性,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()配置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{ //第一個引數 範型型別的元件 //根據當前要保護元件 的狀態 判斷當前使用者是否能夠離開 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中宣告商品資訊型別。
export class Product{ constructor(public id:number, public name:string){ } }在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{ constructor(private router: Router) { } resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | 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; } } } View Code
路由配置: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){ } }View Code
這裡是商品資訊元件
商品id是: {{productId}}
商品名稱是: {{productName}}
效果:
點商品詳情連結,傳入商品ID為2,在resolve守衛中是正確id,會返回一條商品資料。
點商品詳情按鈕,傳入商品ID是3,是錯誤id,會直接跳轉到主頁。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4686/viewspace-2808891/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [NGX]Angular路由守衛初探(1)Angular路由
- Angular專案路由配置與導航守衛Angular路由
- Angular入門到精通系列教程(13)- 路由守衛(Route Guards)Angular路由
- Vue | 路由守衛面試常考Vue路由面試
- vue2.0 實現路由守衛Vue路由
- Vue 導航守衛(路由的生命週期)Vue路由
- Angular路由——子路由Angular路由
- Java登陸第四十天——Router路由守衛Java路由
- Angular路由——路由基礎Angular路由
- Angular路由——輔助路由Angular路由
- vue2.0全域性路由守衛(全域性控制登入)Vue路由
- angular路由傳參Angular路由
- Angular4+路由Angular路由
- angular 路由傳參Angular路由
- angular 巢狀路由Angular巢狀路由
- 如何實現一個react-router路由攔截(導航守衛)React路由
- 2024-07-18 給vue專案新增自定義路由守衛Vue路由
- Angular路由——在路由時候傳遞資料Angular路由
- 使用Angular CLI生成路由Angular路由
- 路由器被黑?被篡改?路由衛士一鍵搞定路由器
- angular路由中的惰性載入Angular路由
- Vue的鉤子函式[路由導航守衛、keep-alive、生命週期鉤子]Vue函式路由Keep-Alive
- angular4學習記錄 — 路由Angular路由
- angular路由高亮--長明燈RouterLinkActiveAngular路由
- 【Angular】——路由之重新整理報404Angular路由
- 路由器被“黑產”盯上了!如何打好路由器的“保衛戰”?路由器
- @angular/router 原始碼分析之註冊路由Angular原始碼路由
- (系列十一)Vue3框架中路由守衛及請求攔截(實現前後端互動)Vue框架路由後端
- 搭建Vue從Vue-cli到router路由護衛Vue路由
- angular4定義路由遇到的那些事Angular路由
- 在angular路由中使用正規表示式Angular路由
- Vue — 導航守衛Vue
- Vue總結第五天:vue-router (使用模組化(建立Vue元件)機制程式設計)、router-link 標籤的屬性、路由程式碼跳轉、懶載入、路由巢狀(子路由)、路由傳遞資料、導航守衛)Vue元件程式設計路由巢狀
- angular當router使用userhash:false時路由404問題AngularFalse路由
- Angular專案下一個路由如何接收到上一個路由url中的引數idAngular路由
- 前端路由(手寫路由)前端路由
- Laravel guard 菊花守衛者Laravel
- 守衛者的挑戰