Angular 入坑記錄的筆記第五篇,由於一直在加班的緣故拖了有一個多月,主要是介紹在 Angular 中如何配置路由,完成重定向以及參數傳遞。至於路由守衛、路由懶加載等「高級」特性,並不會在本篇文章中呈現css
對應官方文檔地址:html
配套代碼地址:angular-practice/src/router-tutorialgit
在 Angular 應用中,框架會自動將 index.html 文件中的 base url 配置做爲組件、模板和模塊文件的基礎路徑地址。默認的狀況下 app 文件夾是整個應用的根目錄,因此咱們直接使用 index.html 中使用默認的 <base href='/'>
便可程序員
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>RouterTutorial</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
複製代碼
在 Angular 項目中,系統的路由須要咱們將一個 url 地址映射到一個展現的組件,所以須要手動的去設置 url 與組件之間的映射關係github
由於咱們在使用 Angular CLI 建立項目時,選擇了添加路由模組,所以咱們能夠直接在 app-routing.module.ts 文件中完成路由的定義。最終咱們定義的路由信息,都會在根模塊中被引入到整個項目typescript
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
import { PagenotfoundComponent } from './components/pagenotfound/pagenotfound.component';
import { NewsComponent } from './components/news/news.component';
import { ProductComponent } from './components/product/product.component';
// 配置路由信息
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'news', component: NewsComponent },
{ path: 'product', component: ProductComponent },
{ path: '**', component: PagenotfoundComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
複製代碼
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule // 引入路由配置信息
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
複製代碼
當定義好路由信息後,咱們須要在頁面上使用 <router-outlet>
標籤來告訴 Angular 在何處渲染出頁面。對於路由之間的跳轉,咱們能夠在 a
標籤上經過使用 RouterLink
指令來綁定具體的路由來完成地址的跳轉編程
<div class="card-container">
<a class="card" [routerLink]="[ '/news' ]" routerLinkActive="active">
<span>News</span>
</a>
<a class="card" [routerLink]="[ '/product' ]" routerLinkActive="active">
<span>Product</span>
</a>
</div>
<div class="card-container">
<div class="form-card">
<!-- 組件渲染的出口 -->
<router-outlet></router-outlet>
</div>
</div>
</div>
複製代碼
固然,若是你非要本身給本身找事,就是要用 a
標籤的 href
屬性進行跳轉,固然也是能夠的,不過在後面涉及到相關框架的功能時就會顯得有點不辣麼聰明的樣子了bootstrap
在廣泛狀況下,對於進入系統後的默認路徑,咱們會選擇重定向到一個具體的地址上,這裏咱們在定義路由信息時,定義了一個空路徑用來表示系統的默認地址,當用戶請求時,重定向到 /home
路徑上,由於只有完整的 url 地址匹配空字符串時才應該進行重定向操做,因此這裏須要指定匹配模式是所有匹配數組
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: '', redirectTo: 'home', pathMatch: 'full' }
];
複製代碼
Angular 在解析路由時,是按照咱們定義路由時的順序依次進行的,一旦匹配就會當即終止。所以,相似於 404 錯誤的這種通配的路由配置,由於能夠匹配上每一個 url 地址,因此應該在定義時放到最後app
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'news', component: NewsComponent },
{ path: 'product', component: ProductComponent },
{ path: '**', component: PagenotfoundComponent },
];
複製代碼
從截圖中能夠看到,當咱們打開系統時,會自動跳轉到咱們指定的 home 路徑,點擊菜單按鈕後,則會加載對應的組件頁面
不少狀況下,對於被選中的路由,咱們可能會添加一個特定的樣式來進行提示用戶,所以,在咱們定義 router-link
時,可使用 routerLinkActive
屬性綁定一個 css 的樣式類,當該連接對應的路由處於激活狀態時,則自動添加上指定的樣式類
在進行路由跳轉時,很常見的一種使用狀況是咱們須要將某些數據做爲參數傳遞到下一個頁面中,例如從列表中選擇點擊某一行數據,跳轉到對應的詳情頁面
常見的參數傳遞有以下的兩種方式
最多見的一種參數傳遞的方式,在須要跳轉的路由地址後面加上參數和對應的值,在跳轉後的頁面經過獲取參數 key 從而獲取到對應的參數值
<a href="www.yoursite.com/product?productId=xxxx">跳轉</a>
複製代碼
對於直接經過 a 標籤進行的路由跳轉,咱們能夠在 a 標籤上經過綁定 queryParams 屬性來添加查詢參數信息
這裏經過 queryParams 屬性綁定的是一個對象,Angular 會自動的幫咱們將這個參數對象與 url 進行拼接。對於參數對象中的屬性(key)對應的屬性值(value),咱們能夠綁定一個組件中的屬性進行動態的賦值,也能夠經過添加單引號將參數值做爲一個固定的數值,例如在下面代碼中的兩個查詢參數就是固定的值
<a class="card" [routerLink]="[ '/news' ]" routerLinkActive="active" [queryParams]="{category:'social',date:'2020-05-02'}">News</a>
複製代碼
一樣的,咱們也能夠在 js 中完成路由的跳轉,對於這種使用場景,咱們須要在進行 js 跳轉的組件類中經過構造函數依賴注入 Router 類,以後經過 Router 類的 navigate 方法完成路由的跳轉;對於可能存在的查詢參數,咱們須要定義一個 NavigationExtras 類型的變量來進行設置
import { Component, OnInit } from '@angular/core';
// 引入路由模塊
import { Router, NavigationExtras } from '@angular/router';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit(): void {}
/** * 使用 js 的方式經過 query 查詢字符串的形式傳遞參數 */
queryNavigate() {
// 查詢參數
let query: NavigationExtras = {
queryParams: {
category: 'social',
date: '2020-05-04'
}
};
this.router.navigate(['/news' ], query);
}
}
複製代碼
既然在進行跳轉時附加了參數信息,在跳轉後的頁面咱們確定須要獲取到傳遞的參數值。在 Angular 中,須要在組件類中依賴注入 ActivatedRoute 來獲取傳遞的參數信息
這裏的 queryParamMap 是一個 Observable 對象,因此這裏須要使用 subscribe 方法來獲取傳遞的參數值
import { Component, OnInit } from '@angular/core';
// 引入路由模塊
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.scss']
})
export class NewsComponent implements OnInit {
constructor(private route: ActivatedRoute) { }
ngOnInit(): void {
this.route.queryParamMap.subscribe((data: any) => {
console.log(data.params);
});
}
}
複製代碼
與使用查詢參數不一樣,使用動態路由進行參數傳值時,須要咱們在定義路由時就提供參數的佔位符信息,例如在下面定義路由的代碼裏,對於組件所需的參數 newsId,咱們須要在定義路由時就指明
const routes: Routes = [
{ path: 'news/detail/:newsId', component: NewsDetailComponent },
];
複製代碼
對於採用動態路由進行的路由跳轉,在 a 標籤綁定的 routerLink 屬性數組的第二個數據中,須要指定咱們傳遞的參數值。例如這裏的 item.newsId 變量就是咱們須要傳遞的參數值
<ul>
<li *ngFor="let item of newsList; let i = index">
<a [routerLink]="['/news/detail', item.newsId]" routerLinkActive="active" >
{{item.title}}
</a>
</li>
</ul>
複製代碼
而採用 js 的方式進行跳轉時,咱們一樣須要使用依賴注入的方式注入 Router 類,而後調用 navigate 方法進行跳轉。與使用 query 查詢參數傳遞數據不一樣,此時須要將跳轉的連接與對應的參數值組合成爲一個數組參數進行傳遞
import { Component, OnInit } from '@angular/core';
// 引入路由模塊
import { Router, ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.scss']
})
export class NewsComponent implements OnInit {
newsList: any;
constructor(private route: ActivatedRoute, private router: Router) {
this.newsList = [{
newsId: 1111,
title: 'lalalalalallaaa'
}, {
newsId: 2222,
title: 'lalalalalallaaa'
}, {
newsId: 3333,
title: 'lalalalalallaaa'
}];
}
ngOnInit(): void {
this.route.queryParamMap.subscribe((data: any) => {
console.log(data.params);
});
}
routerNavigate() {
this.router.navigate(['/news/detail', 11111]);
}
}
複製代碼
在獲取參數數據的組件類中,須要依賴注入 ActivatedRoute 類,由於是採用的動態路由的方式進行的參數傳遞,這裏須要經過 paramMap 屬性獲取到對應的參數值
import { Component, OnInit } from '@angular/core';
// 引入路由模塊
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-news-detail',
templateUrl: './news-detail.component.html',
styleUrls: ['./news-detail.component.scss']
})
export class NewsDetailComponent implements OnInit {
constructor(private route: ActivatedRoute) { }
ngOnInit(): void {
this.route.paramMap.subscribe((data: any) => {
console.log(data.params);
});
}
}
複製代碼
在一些狀況下,路由是存在嵌套關係的,例以下面這個頁面,只有當咱們點擊資源這個頂部的菜單後,它纔會顯示出左側的這些菜單,也就是說這個頁面左側的菜單的父級菜單是頂部的資源菜單
針對這種具備嵌套關係的路由,在定義路由時,咱們須要經過配置 children 屬性來指定路由之間的嵌套關係,例如這裏我定義 ProductDetailComponent 這個組件和 ProductComponent 組件造成的路由之間具備嵌套關係
// 配置路由信息
const routes: Routes = [
{
path: 'product', component: ProductComponent, children: [{
path: 'detail', component: ProductDetailComponent
}, {
path: '', redirectTo: 'detail', pathMatch: 'full'
}]
}
];
複製代碼
由於子路由的渲染出口是在父路由的頁面上,所以當嵌套路由配置完成以後,在嵌套的父級頁面上,咱們須要定義一個 <router-outlet>
標籤用來指定子路由的渲染出口,最終的效果以下圖所示
<h3>我是父路由頁面顯示的內容</h3>
<p>product works!</p>
<!-- 加載子路由的數據 -->
<h3>子路由組件渲染的出口</h3>
<router-outlet></router-outlet>
複製代碼
佔坑
做者:墨墨墨墨小宇
我的簡介:96年生人,出生於安徽某四線城市,畢業於Top 10000000 院校。.NET程序員,槍手死忠,喵星人。於2016年12月開始.NET程序員生涯,微軟.NET技術的堅決堅持者,立志成爲雲養貓的少年中面向谷歌編程最厲害的.NET程序員。
我的博客:yuiter.com
博客園博客:www.cnblogs.com/danvic712