前言

今天是进入公司的第三天,为了能尽快投入项目与成为团队可用的战力,我正在努力啃官方文档学习 Angular 的知识,所以这一篇文章主要是记录我如何阅读官方文档后,实现这个非常基本的、带导航的网页应用。

需求

需求大概是这样的:

  • 开一个新的 Angular 项目,并且一开始选择加入 Router 功能
    • 根组件是 AppComponent ,然后下方有三个子组件分别是
      • page1
      • page2
      • page3
    • 可以在 AppComponent 内点击连结切换到这三个页面

参考文档:

建立环境

输入 ng new ngRouterDemo 建立新项目,并直接选择要使用 Router 。

观察文件结构

这次选择加入 Router 后,发现 app 数据夹内多了 app-routing.module.ts

1
2
3
4
5
6
7
8
9
10
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class { }

然后 app.module.ts 中也把 app-routing.module.ts 这只文件给引入了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class { }

对照一下有无加入 Router 的部分

除此之外就是 app 数据夹内多了 app-routing.module.ts 这只文件。

运行结果

没有什么明显的变化。

分别建立三个组件

输入命令建立本次范例用的组件

  • page1
  • page2
  • page3

ng g c page1

配置路由

因为是选择使用 Router 的模式,所以 Angular CLI 缺省帮我们加入了 router-outlet 标签,这代表路由切换后的画面都会在这个标签里面呈现。

以下引用自官方说明:
RouterOutlet 是一个来自路由模块中的命令,它的用法类似于组件。 它扮演一个占位符的角色,用于在模板中标出一个位置,路由器将会把要显示在这个出口处的组件显示在这里。
有了这份配置,当本应用在浏览器中的 URL 变为 /heroes 时,路由器就会匹配到 path 为 heroes 的 Route,并在宿主检视中的 RouterOutlet 之后显示 HeroListComponent 组件。

加入 RouterLink 连结

因为要点击连结后透过路由配置切换到该组件,所以必须先设置路由器连结 (Router links):

对 Appcomponent 进行 Template 上的调整

1
2
3
4
5
6
7
8
9
10
11
12
13
<h1>点击以下连结切换组件</h1>
<ul>
<li>
<a routerLink="/page1" routerLinkActive="active">Page1</a>
</li>
<li>
<a routerLink="/page2" routerLinkActive="active">Page2</a>
</li>
<li>
<a routerLink="/page3" routerLinkActive="active">Page3</a>
</li>
</ul>
<router-outlet></router-outlet>
  • RouterLink
    • a 标签上的 RouterLink 命令让路由器得以控制这个 a 元素,这里的导航路径是固定的,因此可以把一个字符串赋给 routerLink(”一次性”绑定)。
    • 这后面接的就是实际上地址栏显示的路径
  • RouterLinkActive
    • 在每个 a 标签上,你会看到一个 RouterLinkActive 的属性绑定,像是 routerLinkActive="..."
    • 等号右边可以填入包含一些用空格分隔的 CSS 类名,当这个连结启用时,路由器将会把它们加上去
      • 并在处于非活动状态时移除

为了方便辨识效果,所以也加入 .active 的模式吧

1
2
3
.active{
color: red;
}

这边要注意的是 CSS 模式要写在 Appcomponent 内。

注册路由器与路由定义

要使用路由的话,必须要把要使用的组件 import 进来,并且在 routes 数组内配置它们,数组内传入一个对象,而对象内可以传入参数:

  • path - 切换到这个组件的路径
  • component - 切换的组件名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Page1Component } from './page1/page1.component';
import { Page2Component } from './page2/page2.component';
import { Page3Component } from './page3/page3.component';

const routes: Routes = [ 大专栏  [从 0 开始的 Angular 生活]No.38 实现一个 Angular Router 切换组件页面(一)
{ path: 'page1', component: Page1Component },
{ path: 'page2', component: Page2Component },
{ path: 'page3', component: Page3Component },
];

@NgModule({
imports: [
RouterModule.forRoot(routes, { enableTracing: true })
],
exports: [RouterModule]
})
export class AppRoutingModule { }

当我们定义好路由数组 routes 并把它传给 RouterModule.forRoot() 方法后:

  • 它会返回一个模块,其中包含配置好的 Router 服务提供商,以及路由库所需的其它提供商。

一旦激活了应用 Router 就会根据当前的浏览器 URL 进行首次导航。

存档,试着运行看看。

这样基础的 Angular 路由范例就完成了!

而因为我们有在 RouterModule.forRoot() 把 enableTracing 打开,所以当切换路由时时可以看到一些额外消息:

设置万用符与缺省路由

虽然我们基础的范例完成了但还不够好,因为:

  • 如果在地址栏随意输入会跳出错误
    • 而使用者是这么白目
  • 需要设定一组缺省路由,也就是使用者初次进入网页时会显示的画面

设置万用符

新增一个万用符路由来拦截所有无效的 URL 并处理它们。 万用符路由的 path 是两个星号(**),它会匹配任何 URL。 当路由器匹配不上以前定义的那些路由时,它就会选择这个路由。

万用符路由可以导航到自订的 “404 Not Found” 组件,也可以重定向到一个现有路由。

特别要注意的是:
路由器使用先匹配者优先的策略来选择路由,万用符路由是路由配置中最没有特定性的那个,因此务必确保它是配置中的最后一个路由。

因此修改 app-routing.module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Page1Component } from './page1/page1.component';
import { Page2Component } from './page2/page2.component';
import { Page3Component } from './page3/page3.component';

const routes: Routes = [
{ path: 'page1', component: Page1Component },
{ path: 'page2', component: Page2Component },
{ path: 'page3', component: Page3Component },
{ path: '**', component: Page1Component },
];

@NgModule({
imports: [
RouterModule.forRoot(routes, { enableTracing: true })
],
exports: [RouterModule]
})
export class AppRoutingModule { }

像这样,永远确保万用符在最后一组路由就可以了,而且也不会跳错误。

设置缺省路由

与设置万用符时差不多,由于路由是有顺序性的,因此应该其放在万用符路由的前一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Page1Component } from './page1/page1.component';
import { Page2Component } from './page2/page2.component';
import { Page3Component } from './page3/page3.component';

const routes: Routes = [
{ path: 'page1', component: Page1Component },
{ path: 'page2', component: Page2Component },
{ path: 'page3', component: Page3Component },
{ path: '', redirectTo: 'page2', pathMatch: 'full' },
{ path: '**', component: Page1Component },
];

@NgModule({
imports: [
RouterModule.forRoot(routes, { enableTracing: true })
],
exports: [RouterModule]
})
export class AppRoutingModule { }

为了方便辨识,我将缺省路由设置为 page2 ,也就是预期当使用者初次进入网站时会看到这个画面。

重定向路由需要一个 pathMatch 属性,来告诉路由器如何用 URL 去匹配路由的路径,否则路由器就会报错。

在本范例中路由器应该只有在完整的 URL 等于 ‘’ 时才选择 Page2Component 组件,因此要把 pathMatch 设定为 ‘full’。

可以观察下方的 log ,发现一开始如果网址都没输入时,会自动跳转到 page2

顺序错误的场合

前面提到路由器使用先匹配者优先的策略来选择路由,所以顺序很重要,如果把万用符的顺序稍微挪动,如:

1
2
3
4
5
6
7
const routes: Routes = [
{ path: 'page1', component: Page1Component },
{ path: 'page2', component: Page2Component },
{ path: 'page3', component: Page3Component },
{ path: '**', component: Page1Component },
{ path: '', redirectTo: 'page2', pathMatch: 'full' },
];

因为匹配到的路由会变成万用符的路由,因此就不会跳转到 page2 了。

小结

透过实现这个非常基本的、带导航的网页应用学到了如何:

  • 载入路由库
  • 在根组件的 Template 中新增一个导览列,导览列中有一些 A 标签、routerLink 命令和 routerLinkActive 命令
  • 在根组件的 Template 中新增一个 router-outlet 命令,页面将会被显示在那里
  • 用 RouterModule.forRoot 配置路由器模块
  • 使用万用符路由来处理无效路由
  • 当应用在空路径下激活时,导航到缺省路由

  • GitHub - 范例源代码

[从 0 开始的 Angular 生活]No.38 实现一个 Angular Router 切换组件页面(一)的更多相关文章

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

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

  2. 从0开始的LeetCode生活—9. Palindrome Number(回文数)

    题目大意: 判断输入的数字是不是回文数.所谓回文数就是正反读都一样的数字,比如说11,121,1221这样子的数字.负数不会是回文数. 解题思路: 思路一:如果这个数是负数,则返回false,否则用一 ...

  3. Angular项目构建指南 - 不再为angular构建而犹豫不决(转)

    如果你不知道什么是Angular或者根本没听说过,那么我接下来所说的对你来说毫无益处,不过如果你打算以后会接触Angular或者干脆要涨涨姿势~读下去还是有点用的. Angular和它之前所出现的其余 ...

  4. 【Angular专题】——(1)Angular,孤傲的变革者

    目录 一. 漫谈Angular 二. 如果你还在使用Angularjs 三. 我计划这样学习Angular技术栈 一. 漫谈Angular Angular,来自Google的前端SPA框架,与Reac ...

  5. angular核心原理解析1:angular自启动过程

    angularJS的源代码整体上来说是一个自执行函数,在angularJS加载完成后,就会自动执行了. angular源代码中: angular = window.angular || (window ...

  6. Angular学习笔记—创建一个angular项目

    开始项目前,你需要先安装node和npm,然后执行npm install -g @angular/cli安装Angular CLI. 如何安装node.js和npm npm使用介绍 1.安装angul ...

  7. [Angular] Bind async requests in your Angular template with the async pipe and the "as" keyword

    Angular allows us to conveniently use the async pipe to automatically register to RxJS observables a ...

  8. Angular入门到精通系列教程(7)- 组件(@Component)基本知识

    1. 概述 2. 创建Component 组件模板 视图封装模式 特殊的选择器 :host inline-styles 3. 总结 环境: Angular CLI: 11.0.6 Angular: 1 ...

  9. Angular中懒加载一个模块并动态创建显示该模块下声明的组件

    angular中支持可以通过路由来懒加载某些页面模块已达到减少首屏尺寸, 提高首屏加载速度的目的. 但是这种通过路由的方式有时候是无法满足需求的. 比如, 点击一个按钮后显示一行工具栏, 这个工具栏组 ...

随机推荐

  1. 软件设计之基于Java的连连看小游戏(三)——所有功能的实现

    新年快乐!期末接二连三的考试实在太忙了忘记连连看没有更新完,今天想要学习生信时才发现.所以这次直接把连连看所有功能全部放上. 在传统的连连看的基础上,我增加了上传头像的功能,即可以自行上传图片作为游戏 ...

  2. (转)jpbc的基本函数介绍

    双线性群简介 质数阶双线性群(Prime-Order Bilinear Groups) 质数双线性群可以由五元组(p,G1,G2,GT,e)来描述.五元组中p是一个与给定安全常数λ相关的大质数,G1, ...

  3. kaggle——TMDB 电影票房收入预测

    介绍 看电影是目前人们休闲娱乐,消遣时光的选择之一.我们都知道,有些电影的票房很高,有的电影票房却很低,那么决定票房的因素是什么呢?本次将介绍,如何根据电影上映前的一些信息来预测出该电影的票房. 知识 ...

  4. 特斯拉私有化VS蔚来上市,电动汽车站在十字路口上

    当下,对于电动汽车来说既是一个最好的时代,也是一个最坏的时代.好的一面是业界.投资者.消费者对电动汽车的关注度愈来愈高,坏的一面则是电动汽车正处于一个非常尴尬的处境.从大环境来看,电动汽车自身的产品力 ...

  5. JSP页面中提示JSTL标签无法找到的错误

    无法解析标签库的错误 1.应该是项目中少了jstl.jar和 standard.jar这两个jar包. 下载地址:https://www.onlinedown.net/soft/1162736.htm ...

  6. Python与mongo交互

    # 导入模块 import pymongo # 连接MongoDB数据库 conn = pymongo.MongoClient('localhost', 27017) # 建库 db = conn.g ...

  7. 干货 | IP高防使用配置

    一.知识简介 DoS(Denial of Service),即拒绝服务攻击.该攻击是利用目标系统网络服务功能缺陷或者直接消耗其系统资源,目的是使该目标客户的系统不可用,无法提供正常的服务. DDoS( ...

  8. 吴裕雄--天生自然MySQL学习笔记:MySQL 管理

    启动及关闭 MySQL 服务器 Windows 系统下 在 Windows 系统下,打开命令窗口(cmd),进入 MySQL 安装目录的 bin 目录. 启动: cd c:/mysql/bin mys ...

  9. VMware下的Ubuntu16设置连接主机网络,设置主机下可以通过xshell访问 VMware下的Ubuntu

    NAT模式连接 1. 2. 3. 4. 5. 6.

  10. nginx四层负载及动静分离

    阿里云实验10.0.0.132 LB10.0.0.133 web0110.0.0.134 web02 步骤:1.安装nginx1.14 获取官网repo文件 yum install -y nginx ...