一、Overview

Angular 入坑记录的笔记第五篇,因为一直在加班的缘故拖了有一个多月,主要是介绍在 Angular 中如何配置路由,完成重定向以及参数传递。至于路由守卫、路由懒加载等“高级”特性,并不会在本篇文章中呈现

对应官方文档地址:

配套代码地址:angular-practice/src/router-tutorial

二、Contents

  1. Angular 从入坑到弃坑 - Angular 使用入门
  2. Angular 从入坑到挖坑 - 组件食用指南
  3. Angular 从入坑到挖坑 - 表单控件概览
  4. Angular 从入坑到挖坑 - HTTP 请求概览
  5. Angular 从入坑到挖坑 - Router 路由使用入门指北

三、Knowledge Graph

四、Step by Step

4.1、基础概念

4.1.1、base url

在 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>
4.1.2、路由的配置

在 Angular 项目中,系统的路由需要我们将一个 url 地址映射到一个展示的组件,因此需要手动的去设置 url 与组件之间的映射关系

因为我们在使用 Angular CLI 创建项目时,选择了添加路由模组,因此我们可以直接在 app-routing.module.ts 文件中完成路由的定义。最终我们定义的路由信息,都会在根模块中被引入到整个项目

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 属性进行跳转,当然也是可以的,不过在后面涉及到相关框架的功能时就会显得有点不辣么聪明的样子了

4.1.3、重定向与通配地址

在普遍情况下,对于进入系统后的默认路径,我们会选择重定向到一个具体的地址上,这里我们在定义路由信息时,定义了一个空路径用来表示系统的默认地址,当用户请求时,重定向到 /home 路径上,因为只有完整的 url 地址匹配空字符串时才应该进行重定向操作,所以这里需要指定匹配模式是全部匹配

const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: '', redirectTo: 'home', pathMatch: 'full' }
];

Angular 在解析路由时,是按照我们定义路由时的顺序依次进行的,一旦匹配就会立即终止。因此,类似于 404 错误的这种通配的路由配置,因为可以匹配上每个 url 地址,所以应该在定义时放到最后

const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'news', component: NewsComponent },
{ path: 'product', component: ProductComponent },
{ path: '**', component: PagenotfoundComponent },
];

从截图中可以看到,当我们打开系统时,会自动跳转到我们指定的 home 路径,点击菜单按钮后,则会加载对应的组件页面

4.1.4、激活的路由

很多情况下,对于被选中的路由,我们可能会添加一个特定的样式来进行提示用户,因此,在我们定义 router-link 时,可以使用 routerLinkActive 属性绑定一个 css 的样式类,当该链接对应的路由处于激活状态时,则自动添加上指定的样式类

4.2、路由间的参数传递

在进行路由跳转时,很常见的一种使用情况是我们需要将某些数据作为参数传递到下一个页面中,例如从列表中选择点击某一行数据,跳转到对应的详情页面

常见的参数传递有如下的两种方式

4.2.1、query 查询参数传递

最常见的一种参数传递的方式,在需要跳转的路由地址后面加上参数和对应的值,在跳转后的页面通过获取参数 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);
});
} }

4.2.2、动态路由传递

与使用查询参数不同,使用动态路由进行参数传值时,需要我们在定义路由时就提供参数的占位符信息,例如在下面定义路由的代码里,对于组件所需的参数 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);
});
}
}

4.3、嵌套路由

在一些情况下,路由是存在嵌套关系的,例如下面这个页面,只有当我们点击资源这个顶部的菜单后,它才会显示出左侧的这些菜单,也就是说这个页面左侧的菜单的父级菜单是顶部的资源菜单

针对这种具有嵌套关系的路由,在定义路由时,我们需要通过配置 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>

Angular 从入坑到挖坑 - Router 路由使用入门指北的更多相关文章

  1. Angular 从入坑到挖坑 - 路由守卫连连看

    一.Overview Angular 入坑记录的笔记第六篇,介绍 Angular 路由模块中关于路由守卫的相关知识点,了解常用到的路由守卫接口,知道如何通过实现路由守卫接口来实现特定的功能需求,以及实 ...

  2. Angular 从入坑到挖坑 - 模块简介

    一.Overview Angular 入坑记录的笔记第七篇,介绍 Angular 中的模块的相关概念,了解相关的使用场景,以及知晓如何通过特性模块来组织我们的 Angular 应用 对应官方文档地址: ...

  3. Angular 从入坑到挖坑 - 组件食用指南

    一.Overview angular 入坑记录的笔记第二篇,介绍组件中的相关概念,以及如何在 angular 中通过使用组件来完成系统功能的实现 对应官方文档地址: 显示数据 模板语法 用户输入 组件 ...

  4. Angular 从入坑到挖坑 - 表单控件概览

    一.Overview angular 入坑记录的笔记第三篇,介绍 angular 中表单控件的相关概念,了解如何在 angular 中创建一个表单,以及如何针对表单控件进行数据校验. 对应官方文档地址 ...

  5. Angular 从入坑到挖坑 - HTTP 请求概览

    一.Overview angular 入坑记录的笔记第四篇,介绍在 angular 中如何通过 HttpClient 类发起 http 请求,从而完成与后端的数据交互. 对应官方文档地址: Angul ...

  6. Angular 从入坑到挖坑 - Angular 使用入门

    一.Overview angular 入坑记录的笔记第一篇,完成开发环境的搭建,以及如何通过 angular cli 来创建第一个 angular 应用.入坑一个多星期,通过学习官方文档以及手摸手的按 ...

  7. 【转】angular指令入坑

    独立作用域和函数参数 通过使用本地作用域属性,你可以传递一个外部的函数参数(如定义在控制器$scope中的函数)到指令.这些使用&就可以完成.下面是一个例子,定义一个叫做add的本地作用域属性 ...

  8. webpack入坑之旅(一)入门安装

    学习一个新的东西,首先第一步就是安装,有时候会遇到各种奇葩的问题 至于什么是webpack我这里就不介绍了,请参考官网:https://github.com/webpack/webpack 安装 前提 ...

  9. web前端入坑第五篇:秒懂Vuejs、Angular、React原理和前端发展历史

    秒懂Vuejs.Angular.React原理和前端发展历史 2017-04-07 小北哥哥 前端你别闹 今天来说说 "前端发展历史和框架" 「前端程序发展的历史」 「 不学自知, ...

随机推荐

  1. 详解JS闭包概念

    闭包理解 1.  如何产生闭包?    *当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,产生闭包 2.  闭包到底是什么?    * 使用Chrome调试查看    * 理解一 ...

  2. [Laravel] 自带分页实现以及links方法不存在错误

    自带分页实现其实挺简单的,但是我在实现的时候报错!找了很久才找出原因! 废话不说上码 控制器LeeController.php层 <?php namespace App\Http\control ...

  3. [PHP]PHP设计模式:单例模式

    单例模式(职责模式): 简单的说,一个对象(在学习设计模式之前,需要比较了解面向对象思想)只负责一个特定的任务: 单例类: 1.构造函数需要标记为private(访问控制:防止外部代码使用new操作符 ...

  4. kubernetes的cni0和flannel.1的关系?

    当容器运行之后,节点之间多了个虚拟接口cni0,它是由flanneld创建的一个虚拟网桥叫cni0,供pod本地通信使用.flanneld为每个pod创建一对veth虚拟设备,一端放在容器接口上,一端 ...

  5. python face_recognition模块实现人脸识别

    import face_recognition #人脸识别库 pip cmake dlib import cv2 #读取图像 face_image1 = face_recognition.load_i ...

  6. 数据挖掘入门系列教程(十点五)之DNN介绍及公式推导

    深度神经网络(DNN,Deep Neural Networks)简介 首先让我们先回想起在之前博客(数据挖掘入门系列教程(七点五)之神经网络介绍)中介绍的神经网络:为了解决M-P模型中无法处理XOR等 ...

  7. scrapy爬虫实例(1)

    爬虫实例 对象 阳光问政平台 目标 : 主题,时间,内容 爬取思路 预先设置好items import scrapy class SuperspiderItem(scrapy.Item): title ...

  8. 手把手编写自己的PHP MVC框架实例教程

    1 什么是MVC MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式. MVC把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Contro ...

  9. Data Flow Diagram with Examples - Customer Service System

    Data Flow Diagram with Examples - Customer Service System Data Flow Diagram (DFD) provides a visual ...

  10. Scala教程之:静态类型

    文章目录 泛类型 型变 协变 逆变 不变 类型上界 类型下界 内部类 抽象类型 复合类型 自类型 隐式参数 隐式转换 多态方法 类型推断 Scala是静态类型的,它拥有一个强大的类型系统,静态地强制以 ...