Angular 教程:在单页面应用中导航
在单页面应用中使用 Angular 路由
本教程将介绍如何构建一个使用多个 Angular 路由的单页面应用 SPA。
在 SPA(Single Page Application 单页面应用)中,所有应用的所有功能都存在于同一个 HTML 页面中。当用户访问应用的各种特性时,浏览器只需渲染那些用户需要关心的部分,而不用重新加载页面。这种模式可以显著改善应用的用户体验。
为了定义用户如何在应用中导航,你可以使用路由。可以添加一些路由来定义用户如何从应用的某个部分导航到另一部分。也可以配置一些路由来防范意外或未经授权的行为。
目标
- 将范例应用的各个特性组织到一些模块中。
- 定义如何导航到组件。
- 使用参数把信息传给组件。
- 通过嵌套多个路由来构造路由体系。
- 检查用户是否可以访问路由。
- 控制该应用是否可以放弃未保存的更改。
- 通过预先获取路由数据和惰性加载特性模块来提高性能。
- 需要特定的条件来加载组件。
创建一个范例应用
使用 Angular CLI,创建一个新的应用angular-router-sample。这个应用程序有两个组件:crisis-list和heroes-list。
- 创建一个新的 Angular 项目 angular-router-sample。
- 在终端上,导航到
angular-router-sample
目录。 - 创建一个组件 crisis-list。
- 在你的代码编辑器中,找到文件
crisis-list.component.html
并用如下 HTML 替换占位符内容。 - 创建第二个组件
heroes-list
。 - 在你的代码编辑器中,找到
heroes-list.component.html
文件,并用如下 HTML 替换占位符内容。 - 在你的代码编辑器中,打开文件
app.component.html
并用如下 HTML 替换其内容。 - 运行
ng serve
来验证新应用是否正常运行。 - 打开浏览器访问
http://localhost:4200
。
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
就准备就绪了。
ng generate component crisis-list
<h3>CRISIS CENTER</h3>
<p>Get your crisis here</p>
ng generate component heroes-list
<h3>HEROES</h3>
<p>Get your heroes here</p>
<h1>Angular Router Sample</h1>
<app-crisis-list></app-crisis-list>
<app-heroes-list></app-heroes-list>
ng serve
你会看到一个网页,它由一个标题和两个组件的 HTML 组成。
从 @angular/router 导入 RouterModule
路由允许你根据 URL 路径显示应用的特定视图。要把这个功能添加到你的范例应用中,你需要更新 app.module.ts
文件以使用模块 RouterModule
。你可以从 @angular/router
导入该模块。
- 在代码编辑器中,打开
app.module.ts
文件。 - 添加如下
import
语句。
import { RouterModule } from '@angular/router';
定义你的各个路由
在本节中,你将定义两个路由:
- 路由
/crisis-center
用来打开 crisis-center
组件。 - 路由
/heroes-list
用来打开 heroes-list
组件。
路由定义是一个 JavaScript 对象。每个路由通常都有两个属性。第一个属性 path
是一个字符串,它指定路由的 URL 路径。第二个属性 component
是组件类,它指定应用要为该路由显示哪个组件。
- 在代码编辑器中,打开
app.module.ts
文件。 - 找到
@NgModule()
部分。 - 用如下代码替换这部分的
imports
数组。
imports: [
BrowserModule,
RouterModule.forRoot([
{path: 'crisis-list', component: CrisisListComponent},
{path: 'heroes-list', component: HeroesListComponent},
]),
],
这段代码把 RouterModule
添加到了 imports
数组中。接下来,该代码使用 RouterModule
的 forRoot()
方法来定义你的两个路由。该方法接受一个 JavaScript 对象数组,每个对象定义一个路由的属性。forRoot()
方法确保你的应用只会实例化一个 RouterModule
。
更新你的组件以添加 router-outlet
此刻,你已经为应用定义了两个路由。但是,你的应用仍然在你的 app.component.html
模板中硬编码着 crisis-list
和 heroes-list
组件。为了让你的路由正常工作,需要更新模板,以便根据 URL 路径动态加载一个组件。
要实现这个功能,你就可以把 router-outlet
指令添加到模板文件中。
- 在代码编辑器中,打开
app.component.html
文件。 - 删除下面这几行。
- 添加
router-outlet
指令。
<app-crisis-list></app-crisis-list>
<app-heroes-list></app-heroes-list>
<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-list
和 crisis-list
组件之间导航。你还会添加一些 CSS 样式。虽然这些样式不是必需的,但它们可以让你更容易的识别出当前显示的组件的链接。你将在下一节中添加此功能。
- 打开
app.component.html
文件,在标题下方添加以下 HTML。 - 打开
app.component.css
文件并添加如下样式。
<nav>
<a class="button" routerLink="/crisis-list">Crisis Center</a> |
<a class="button" routerLink="/heroes-list">Heroes</a>
</nav>
这个 HTML 使用了 Angular 指令 routerLink
。该指令将你定义的路由连接到模板文件中。
.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-radius: 6px;
border: 1px solid #84bbf3;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: Arial, sans-serif;
font-size: 15px;
font-weight: bold;
padding: 6px 24px;
text-decoration: none;
text-shadow: 0 1px 0 #528ecc;
outline: 0;
}
如果你在浏览器中查看应用,你会看到这两个链接。单击某个链接时,会出现相应的组件。
标出活动路由
虽然用户可以使用上一节中添加的链接来浏览你的应用,但他们并没有简单的方法来确定活动路由是什么。可以用 Angular 的 routerLinkActive
指令添加这个功能。
- 在代码编辑器中,打开
app.component.html
文件。 - 更新 a 标签以包含
routerLinkActive
指令。
<nav>
<a class="button"
routerLink="/crisis-list"
routerLinkActive="activebutton"
ariaCurrentWhenActive="page">
Crisis Center
</a> |
<a class="button"
routerLink="/heroes-list"
routerLinkActive="activebutton"
ariaCurrentWhenActive="page">
Heroes
</a>
</nav>
再次查看你的申请表。单击其中一个按钮时,该按钮的样式会自动更新,并为该用户标出该活动组件。通过添加 routerLinkActive
指令,可以通知你的应用把一个特定的 CSS 类应用到当前的活动路由中。在本教程中,这个 CSS 类是 activebutton
,但你可以使用任何想要的类。
请注意,我们还为 routerLinkActive
的 ariaCurrentWhenActive
指定了一个值。这可确保视障用户(他们可能无法感知正在应用的不同样式)也可以识别活动按钮。
添加一个重定向
在本教程的这一步中,你将添加一个重定向路由来把用户导向 /heroes-list
组件。
- 在代码编辑器中,打开
app.module.ts
文件。 - 在
imports
数组中,按如下所示更新 RouterModule
部分。
imports: [
BrowserModule,
RouterModule.forRoot([
{path: 'crisis-list', component: CrisisListComponent},
{path: 'heroes-list', component: HeroesListComponent},
{path: '', redirectTo: '/heroes-list', pathMatch: 'full'},
]),
],
注意这个新路由使用一个空字符串作为它的路径。另外,它还把 component
属性替换成了这两个新属性:
属性 |
详情 |
---|---|
redirectTo
|
这个属性指示 Angular 从空路径重定向到 |
pathMatch
|
这个属性指示 Angular 要如何匹配 URL。对于本教程,你应该把这个属性设置为 |
现在,当你打开应用时,它会默认显示 heroes-list
组件。
添加 404 页面
用户可以尝试访问你尚未定义的路由。为了解决这个问题,最佳做法是显示一个 404 页面。在本节中,你将创建一个 404 页面,并更新路由配置,以便为任何未指定的路由显示该页面。
- 在终端上,创建一个新的组件
PageNotFound
。 - 在代码编辑器中,打开
page-not-found.component.html
文件并用下面的 HTML 替换它的内容。 - 打开
app.module.ts
文件。在其 imports
数组中,按如下所示更新 RouterModule
部分的内容。
ng generate component page-not-found
<h2>Page Not Found</h2>
<p>We couldn't find that page! Not even with x-ray vision.</p>
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
组件。