一、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. 怎么在执行Python脚本时,密码等敏感信息也不让它出现

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http ...

  2. Linux编辑利器-Vim

    在大学时代,Vim 的大名就已如雷贯耳,但由于它陡峭的学习曲线,一直望而却步.等真正开始学习之后,发现并没有想象中的复杂,也没有所谓的瓶颈,只要在实际写代码中强迫自己使用就可以了,无形中就会形成习惯. ...

  3. Linux学习笔记(七)关机、重启及常用的网络命令

    关机.重启命令 sync shutdown reboot init sync 英文原意:flush file system buffers 功能:刷新文件系统缓冲区,将内存中的数据保存到硬盘中 语法: ...

  4. kafka消息分区机制原理

    背景 kafka如何支撑海量消息的集中写入? 答案就是消息分区. 核心思想是:负载均衡,采用合适的分区策略把消息写到不同的broker上的分区中: 其它的产品中有类似的思想. 比如monogodb, ...

  5. 使用mysqlbinlog查看二进制日志

    (一)mysqlbinlog工具介绍 binlog类型是二进制的,也就意味着我们没法直接打开看,MySQL提供了mysqlbinlog来查看二进制日志,该工具类似于Oracle的logminer.my ...

  6. webpack3 babel相关

    babel 链接地址 在index.js中写入js6的语法如 let fn = (){ console.log('this is es6') } 执行npm run build 在打包出来的js文件中 ...

  7. hash算法解决冲突的方案

    1, 开放定址法: 所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入 公式为:fi(key) = (f(key)+di) MOD m ...

  8. 【Linux网络基础】网络子网划分基础知识(IP地址,子网)

    一. IP地址分类与子网划分基础 1. 什么是IP地址? 常见的ip地址版本为ipv4, ipv6 32位 4 * 8=32位. 32位二进制数字序列组成的数字序列   点分十进制 采用点将32位数字 ...

  9. Spark 源码系列(六)Shuffle 的过程解析

    Spark 大会上,所有的演讲嘉宾都认为 shuffle 是最影响性能的地方,但是又无可奈何.之前去百度面试 hadoop 的时候,也被问到了这个问题,直接回答了不知道. 这篇文章主要是沿着下面几个问 ...

  10. PostgreSQL 10.0 preview 性能增强 - 分区表性能增强(plan阶段加速)

    标签 PostgreSQL , 10.0 , 分区表 , 子表 , 元信息搜索性能增强 背景 PostgreSQL 10.0 增强了分区表的子表搜索性能,对于涉及分区表包含子表特别多的QUERY,可以 ...