# 在单页面应用中使用 Angular 路由

本教程将介绍如何构建一个使用多个 Angular 路由的单页面应用 SPA。

在 SPA(Single Page Application 单页面应用)中,所有应用的所有功能都存在于同一个 HTML 页面中。当用户访问应用的各种特性时,浏览器只需渲染那些用户需要关心的部分,而不用重新加载页面。这种模式可以显著改善应用的用户体验。

为了定义用户如何在应用中导航,你可以使用路由。可以添加一些路由来定义用户如何从应用的某个部分导航到另一部分。也可以配置一些路由来防范意外或未经授权的行为。

要探索本教程的范例应用,请参阅现场演练/ 下载范例

# 目标

  • 将范例应用的各个特性组织到一些模块中。

  • 定义如何导航到组件。

  • 使用参数把信息传给组件。

  • 通过嵌套多个路由来构造路由体系。

  • 检查用户是否可以访问路由。

  • 控制该应用是否可以放弃未保存的更改。

  • 通过预先获取路由数据和惰性加载特性模块来提高性能。

  • 需要特定的条件来加载组件。

# 前提条件

要完成本教程,你应该对以下概念有基本的了解:

  • JavaScript
  • HTML
  • CSS
  • Angular CLI

你可能会发现《英雄之旅》教程很有用,但这不是必需的。

# 创建一个范例应用

使用 Angular CLI,创建一个新的应用angular-router-sample。这个应用程序有两个组件:crisis-list和heroes-list。

  • 创建一个新的 Angular 项目 angular-router-sample。
ng new angular-router-sample

当系统提示 Would you like to add Angular routing?时,选择 N

当系统提示 Which stylesheet format would you like to use?时,选择 CSS

一段时间后,一个新项目 angular-router-sample就准备就绪了。

  • 在终端上,导航到 angular-router-sample目录。

  • 创建一个组件 crisis-list。

ng generate component crisis-list
  • 在你的代码编辑器中,找到文件 crisis-list.component.html并用如下 HTML 替换占位符内容。

src/app/crisis-list/crisis-list.component.html

<h3>CRISIS CENTER</h3>
<p>Get your crisis here</p>
  • 创建第二个组件 heroes-list
ng generate component heroes-list
  • 在你的代码编辑器中,找到 heroes-list.component.html文件,并用如下 HTML 替换占位符内容。

src/app/heroes-list/heroes-list.component.html

<h3>HEROES</h3>
<p>Get your heroes here</p>
  • 在你的代码编辑器中,打开文件 app.component.html并用如下 HTML 替换其内容。

src/app/app.component.html

<h1>Angular Router Sample</h1>
<app-crisis-list></app-crisis-list>
<app-heroes-list></app-heroes-list>
  • 运行 ng serve来验证新应用是否正常运行。
ng serve
  • 打开浏览器访问 http://localhost:4200

你会看到一个网页,它由一个标题和两个组件的 HTML 组成。

#@angular/router导入 RouterModule

路由允许你根据 URL 路径显示应用的特定视图。要把这个功能添加到你的范例应用中,你需要更新 app.module.ts文件以使用模块 RouterModule。你可以从 @angular/router导入该模块。

  • 在代码编辑器中,打开 app.module.ts文件。

  • 添加如下 import语句。

src/app/app.module.ts

import { RouterModule } from '@angular/router';

# 定义你的各个路由

在本节中,你将定义两个路由:

  • 路由 /crisis-center用来打开 crisis-center组件。

  • 路由 /heroes-list用来打开 heroes-list组件。

路由定义是一个 JavaScript 对象。每个路由通常都有两个属性。第一个属性 path是一个字符串,它指定路由的 URL 路径。第二个属性 component是组件类,它指定应用要为该路由显示哪个组件。

  • 在代码编辑器中,打开 app.module.ts文件。

  • 找到 @NgModule()部分。

  • 用如下代码替换这部分的 imports数组。

src/app/app.module.ts

imports: [
  BrowserModule,
  RouterModule.forRoot([
    {path: 'crisis-list', component: CrisisListComponent},
    {path: 'heroes-list', component: HeroesListComponent},
  ]),
],

这段代码把 RouterModule添加到了 imports数组中。接下来,该代码使用 RouterModuleforRoot()方法来定义你的两个路由。该方法接受一个 JavaScript 对象数组,每个对象定义一个路由的属性。forRoot()方法确保你的应用只会实例化一个 RouterModule。欲知详情,请参阅单例服务。

# 更新你的组件以添加 router-outlet

此刻,你已经为应用定义了两个路由。但是,你的应用仍然在你的 app.component.html模板中硬编码着 crisis-listheroes-list组件。为了让你的路由正常工作,需要更新模板,以便根据 URL 路径动态加载一个组件。

要实现这个功能,你就可以把 router-outlet指令添加到模板文件中。

  • 在代码编辑器中,打开 app.component.html文件。

  • 删除下面这几行。

src/app/app.component.html

<app-crisis-list></app-crisis-list>
<app-heroes-list></app-heroes-list>
  • 添加 router-outlet指令。

src/app/app.component.html

<router-outlet></router-outlet>

在浏览器中查看更新后的应用。你应该只看到应用标题。要查看 crisis-list组件,就要把 crisis-list添加到浏览器地址栏的路径末尾。比如:

http://localhost:4200/crisis-list

注意,crisis-list组件会显示出来。Angular 正在使用你定义的路由来动态加载组件。你可以用同样的方法加载 heroes-list组件:

http://localhost:4200/heroes-list

# 用 UI 元素控制导航

目前,你的应用支持两种路由。但是目前使用这些路由的唯一方法是让用户在浏览器的地址栏中手动输入路径。在本节中,你要添加两个链接,用户可以单击它们在 heroes-listcrisis-list组件之间导航。你还会添加一些 CSS 样式。虽然这些样式不是必需的,但它们可以让你更容易的识别出当前显示的组件的链接。你将在下一节中添加此功能。

  • 打开 app.component.html文件,在标题下方添加以下 HTML。

src/app/app.component.html

<nav>
  <a class="button" router="/crisis-list">Crisis Center</a> |
  <a class="button" router="/heroes-list">Heroes</a>
</nav>

这个 HTML 使用了 Angular 指令 router。该指令将你定义的路由连接到模板文件中。

  • 打开 app.component.css文件并添加如下样式。

src/app/app.component.css

.button {
    box-shadow: inset 0 1px 0 0 #ffffff;
    background: #ffffff linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%);
    border-radius: 6px;
    border: 1px solid #dcdcdc;
    display: inline-block;
    cursor: pointer;
    color: #666666;
    font-family: Arial, sans-serif;
    font-size: 15px;
    font-weight: bold;
    padding: 6px 24px;
    text-decoration: none;
    text-shadow: 0 1px 0 #ffffff;
    outline: 0;
}
.activebutton {
    box-shadow: inset 0 1px 0 0 #dcecfb;
    background: #bddbfa linear-gradient(to bottom, #bddbfa 5%, #80b5ea 100%);
    border: 1px solid #84bbf3;
    color: #ffffff;
    text-shadow: 0 1px 0 #528ecc;
}

如果你在浏览器中查看应用,你会看到这两个链接。单击某个链接时,会出现相应的组件。

# 标出活动路由

虽然用户可以使用上一节中添加的链接来浏览你的应用,但他们并没有简单的方法来确定活动路由是什么。可以用 Angular 的 routerActive指令添加这个功能。

  • 在代码编辑器中,打开 app.component.html文件。

  • 更新 a 标签以包含 routerActive指令。

src/app/app.component.html

<nav>
  <a class="button"
     router="/crisis-list"
     routerActive="activebutton"
     ariaCurrentWhenActive="page">
    Crisis Center
  </a> |
  <a class="button"
     router="/heroes-list"
     routerActive="activebutton"
     ariaCurrentWhenActive="page">
    Heroes
  </a>
</nav>

再次查看你的申请表。单击其中一个按钮时,该按钮的样式会自动更新,并为该用户标出该活动组件。通过添加 routerActive指令,可以通知你的应用把一个特定的 CSS 类应用到当前的活动路由中。在本教程中,这个 CSS 类是 activebutton,但你可以使用任何想要的类。

请注意,我们还为 routerActiveariaCurrentWhenActive指定了一个值。这可确保视障用户(他们可能无法感知正在应用的不同样式)也可以识别活动按钮。有关更多信息,请参阅无障碍性最佳实践活动链接标识部分。

# 添加一个重定向

在本教程的这一步中,你将添加一个重定向路由来把用户导向 /heroes-list组件。

  • 在代码编辑器中,打开 app.module.ts文件。

  • imports数组中,按如下所示更新 RouterModule部分。

src/app/app.module.ts

imports: [
  BrowserModule,
  RouterModule.forRoot([
    {path: 'crisis-list', component: CrisisListComponent},
    {path: 'heroes-list', component: HeroesListComponent},
    {path: '', redirectTo: '/heroes-list', pathMatch: 'full'},
  ]),
],

注意这个新路由使用一个空字符串作为它的路径。另外,它还把 component属性替换成了这两个新属性:

属性 详情
redirectTo 这个属性指示 Angular 从空路径重定向到 heroes-list 路径。
pathMatch 这个属性指示 Angular 要如何匹配 URL。对于本教程,你应该把这个属性设置为 full。当路径为空字符串时,建议使用此策略。关于此属性的更多信息,请参阅 Route API 文档。

现在,当你打开应用时,它会默认显示 heroes-list组件。

# 添加 404 页面

用户可以尝试访问你尚未定义的路由。为了解决这个问题,最佳做法是显示一个 404 页面。在本节中,你将创建一个 404 页面,并更新路由配置,以便为任何未指定的路由显示该页面。

  • 在终端上,创建一个新的组件 PageNotFound
ng generate component page-not-found
  • 在代码编辑器中,打开 page-not-found.component.html文件并用下面的 HTML 替换它的内容。

src/app/page-not-found/page-not-found.component.html

<h2>Page Not Found</h2>
<p>We couldn't find that page! Not even with x-ray vision.</p>
  • 打开 app.module.ts文件。在其 imports数组中,按如下所示更新 RouterModule部分的内容。

src/app/app.module.ts

imports: [
  BrowserModule,
  RouterModule.forRoot([
    {path: 'crisis-list', component: CrisisListComponent},
    {path: 'heroes-list', component: HeroesListComponent},
    {path: '', redirectTo: '/heroes-list', pathMatch: 'full'},
    {path: '**', component: PageNotFoundComponent}
  ]),
],

新路由使用路径 **。这个路径是 Angular 表示通配符路由的方式。任何与你配置中的路由都不匹配的路由都会使用这个路由。

请注意,通配符路由要放在数组的末尾。路由的顺序很重要,因为 Angular 会按顺序应用路由并使用所找到的第一个匹配项。

尝试导航到应用中不存在的路由,比如 http://localhost:4200/powers。此路由与 app.module.ts文件中定义的所有内容都不匹配。但是,由于你定义了一个通配符路由,该应用会自动显示你的 PageNotFound组件。

# 下一步

你已经有了一个基本的应用程序,它使用 Angular 的路由功能来根据 URL 地址改变用户可以看到的组件。你还扩展了这些特性,以包含一个重定向,以及一个用来显示自定义 404 页面的通配符路由。

关于路由的更多信息,请参阅以下主题:

  • 应用内路由和导航

  • 路由器 API

Last Updated: 5/10/2023, 8:25:49 AM