在单页面应用中使用 Angular 路由
Using Angular routes in a single-page application
本教程将介绍如何构建一个使用多个 Angular 路由的单页面应用 SPA。
This tutorial describes how you can build a single-page application, SPA that uses multiple Angular routes.
在 SPA 中,所有应用的所有功能都存在于同一个 HTML 页面中。当用户访问应用的各种特性时,浏览器只需渲染那些用户需要关心的部分,而不用重新加载页面。这种模式可以显著改善应用的用户体验。
In an SPA, all of your application's functions exist in a single HTML page. As users access your application's features, the browser needs to render only the parts that matter to the user, instead of loading a new page. This pattern can significantly improve your application's user exprience.
为了定义用户如何在应用中导航,你可以使用路由。你可以添加一些路由来定义用户如何从应用的某个部分导航到另一部分。你也可以配置一些路由来防范意外或未经授权的行为。
To define how users navigate through your application, you use routes. You can add routes to define how users navigate from one part of your application to another. You can also configure routes to guard against unexpected or unauthorized behavior.
To explore a sample app featuring the contents of this tutorial, see the
目标
Objectives
将示例应用的各个特性组织到一些模块中。
Organize a sample application's features into modules.
定义如何导航到组件。
Define how to navigate to a component.
使用参数把信息传给组件。
Pass information to a component using a parameter.
通过嵌套多个路由来构造路由体系。
Structure routes by nesting several routes.
检查用户是否可以访问路由。
Check whether users can access a route.
控制该应用是否可以放弃未保存的更改。
Control whether the application can discard unsaved changes.
通过预先获取路由数据和惰性加载特性模块来提高性能。
Improve performance by pre-fetching route data and lazy loading feature modules.
需要特定的条件来加载组件。
Require specific criteria to load components.
先决条件
Prerequisites
要完成本教程,你应该对这些概念有一个基本的了解:
To complete this tutorial, you should have a basic understanding of the following concepts:
- JavaScript
- HTML
- CSS
- Angular CLI
你可能会发现英雄指南教程很有帮助,但它并不是必须的。
You might find the Tour of Heroes tutorial helpful, but it is not required.
创建一个示例应用
Create a sample application
使用 Angular CLI,创建一个新的应用angular-router-sample。这个应用程序有两个组件: crisis-list和heroes-list。
Using the Angular CLI, create a new application, angular-router-sample. This application will have two components: crisis-list and heroes-list.
创建一个新的 Angular 项目 angular-router-sample。
Create a new Angular project, angular-router-sample.
ng new angular-router-sample
当系统提示
Would you like to add Angular routing?
时,选择N
When prompted with
Would you like to add Angular routing?
, selectN
.当系统提示
Which stylesheet format would you like to use?
时,选择CSS
。When prompted with
Which stylesheet format would you like to use?
, selectCSS
.一段时间后,一个新项目
angular-router-sample
就准备就绪了。After a few moments, a new project,
angular-router-sample
, is ready.在终端上,导航到
angular-router-sample
目录。From your terminal, navigate to the
angular-router-sample
directory.创建一个组件 crisis-list。
Create a component, crisis-list.
ng generate component crisis-list
在你的代码编辑器中,找到文件
crisis-list.component.html
并用如下 HTML 替换占位符内容。In your code editor, locate the file,
crisis-list.component.html
and replace the placeholder content with the following HTML.src/app/crisis-list/crisis-list.component.html <h3>CRISIS CENTER</h3> <p>Get your crisis here</p>
创建第二个组件
heroes-list
。Create a second component, heroes-list.
ng generate component heroes-list
在你的代码编辑器中,找到
heroes-list.component.html
文件,并用如下 HTML 替换占位符内容。In your code editor, locate the file,
heroes-list.component.html
and replace the placeholder content with the following HTML.src/app/heroes-list/heroes-list.component.html <h3>HEROES</h3> <p>Get your heroes here</p>
在你的代码编辑器中,打开文件
app.component.html
并用如下 HTML 替换其内容。In your code editor, open the file,
app.component.html
and replace its contents with the following 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
来验证新应用是否正常运行。Verify that your new application runs as expected by running the
ng serve
command.ng serve
打开浏览器访问
http://localhost:4200
。Open a browser to
http://localhost:4200
.你会看到一个网页,它由一个标题和两个组件的 HTML 组成。
You should see a single web page, consisting of a title and the HTML of your two components.
从 @angular/router
导入 RouterModule
Import RouterModule
from @angular/router
路由允许你根据 URL 路径显示应用的特定视图。要把这个功能添加到你的示例应用中,你需要更新 app.module.ts
文件以使用模块 RouterModule
。你可以从 @angular/router
导入该模块。
Routing allows you to display specific views of your application depending on the URL path. To add this functionality to your sample application, you need to update the app.module.ts
file to use the module, RouterModule
. You import this module from @angular/router
.
在代码编辑器中,打开
app.module.ts
文件。From your code editor, open the
app.module.ts
file.添加如下
import
语句。Add the following
import
statement.src/app/app.module.ts import { RouterModule } from '@angular/router';
定义你的各个路由
Define your routes
在本节中,你将定义两个路由:
In this section, you'll define two routes:
路由
/crisis-center
用来打开crisis-center
组件。The route
/crisis-center
opens thecrisis-center
component.路由
/heroes-list
用来打开heroes-list
组件。The route
/heroes-list
opens theheroes-list
component.
路由定义是一个 JavaScript 对象。每个路由通常都有两个属性。第一个属性 path
是一个字符串,它指定路由的 URL 路径。第二个属性 component
是组件类,它指定应用要为该路由显示哪个组件。
A route definition is a JavaScript object. Each route typically has two propteries. The first property, path
, is a string that specifies the URL path for the route. The second property, component
, is a string that specifies what component your application should display for that path.
在代码编辑器中,打开
app.module.ts
文件。From your code editor, open the
app.module.ts
file.找到
@NgModule()
部分。Locate the
@NgModule()
section.用如下代码替换这部分的
imports
数组。Replace the
imports
array in that section with the following.src/app/app.module.ts imports: [ BrowserModule, RouterModule.forRoot([ {path: 'crisis-list', component: CrisisListComponent}, {path: 'heroes-list', component: HeroesListComponent}, ]), ],
这段代码把 RouterModule
添加到了 imports
数组中。接下来,该代码使用 RouterModule
的 forRoot()
方法来定义你的两个路由。该方法接受一个 JavaScript 对象数组,每个对象定义一个路由的属性。forRoot()
方法确保你的应用只会实例化一个 RouterModule
。有关更多信息,请参阅单例服务。
This code adds the RouterModule
to the imports
array. Next, the code uses the forRoot()
method of the RouterModule
to define your two routes. This method takes an array of JavaScript objects, with each object defining the proprties of a route. The forRoot()
method ensures that your application only instantiates one RouterModule
. For more information, see Singleton Services.
更新你的组件以添加 router-outlet
Update your component with router-outlet
此刻,你已经为应用定义了两个路由。但是,你的应用仍然在你的 app.component.html
模板中硬编码着 crisis-list
和 heroes-list
组件。为了让你的路由正常工作,需要更新模板,以便根据 URL 路径动态加载一个组件。
At this point, you have defined two routes for your application. However, your application still has both the crisis-list
and heroes-list
components hard-coded in your app.component.html
template. For your routes to work, you need to update your template to dynamically load a component based on the URL path.
要实现这个功能,你就可以把 router-outlet
指令添加到模板文件中。
To implement this functionality, you add the router-outlet
directive to your template file.
在代码编辑器中,打开
app.component.html
文件。From your code editor, open the
app.component.html
file.删除下面这几行。
Delete the following lines.
src/app/app.component.html <app-crisis-list></app-crisis-list> <app-heroes-list></app-heroes-list>
添加
router-outlet
指令。Add the
router-outlet
directive.src/app/app.component.html <router-outlet></router-outlet>
在浏览器中查看更新后的应用。你应该只看到应用标题。要查看 crisis-list
组件,就要把 crisis-list
添加到浏览器地址栏的路径末尾。例如:
View your updated application in your browser. You should see only the application title. To view the crisis-list
component, add crisis-list
to the end of the path in your browser's address bar. For example:
http://localhost:4200/crisis-list
注意,crisis-list
组件会显示出来。Angular 正在使用你定义的路由来动态加载组件。你可以用同样的方法加载 heroes-list
组件:
Notice that the crisis-list
component displays. Angular is using the route you defined to dynamically load the component. You can load the heroes-list
component the same way:
http://localhost:4200/heroes-list
用 UI 元素控制导航
Control navigation with UI elements
目前,你的应用支持两种路由。但是目前使用这些路由的唯一方法是让用户在浏览器的地址栏中手动输入路径。在本节中,你要添加两个链接,用户可以单击它们在 heroes-list
和 crisis-list
组件之间导航。你还会添加一些 CSS 样式。虽然这些样式不是必需的,但它们可以让你更容易的识别出当前显示的组件的链接。你将在下一节中添加此功能。
Currently, your application supports two routes. However, the only way to use those routes is for the user to manually type the path in the browser's address bar. In this section, you'll add two links that users can click to navigate between the heroes-list
and crisis-list
components. You'll also add some CSS styles. While these styles are not required, they make it easier to identify the link for the currently-displayed component. You'll add that functionality in the next section.
打开
app.component.html
文件,在标题下方添加以下 HTML。Open the
app.component.html
file and add the following HTML below the title.src/app/app.component.html <nav> <a class="button" routerLink="/crisis-list">Crisis Center</a> | <a class="button" routerLink="/heroes-list">Heroes</a> </nav>
这个 HTML 使用了 Angular 指令
routerLink
。该指令将你定义的路由连接到模板文件中。This HTML uses an Angular directive,
routerLink
. This directive connects the routes you defined to your template files.打开
app.component.css
文件并添加如下样式。Open the
app.component.css
file and add the following styles.src/app/app.component.css .button { box-shadow: inset 0px 1px 0px 0px #ffffff; background: linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%); background-color: #ffffff; border-radius: 6px; border: 1px solid #dcdcdc; display: inline-block; cursor: pointer; color: #666666; font-family: Arial; font-size: 15px; font-weight: bold; padding: 6px 24px; text-decoration: none; text-shadow: 0px 1px 0px #ffffff; outline: 0; } .activebutton { box-shadow: inset 0px 1px 0px 0px #dcecfb; background: linear-gradient(to bottom, #bddbfa 5%, #80b5ea 100%); background-color: #bddbfa; border-radius: 6px; border: 1px solid #84bbf3; display: inline-block; cursor: pointer; color: #ffffff; font-family: Arial; font-size: 15px; font-weight: bold; padding: 6px 24px; text-decoration: none; text-shadow: 0px 1px 0px #528ecc; outline: 0; }
如果你在浏览器中查看应用,你会看到这两个链接。单击某个链接时,会出现相应的组件。
If you view your application in the browser, you should see these two links. When you click on a link, the corresponding component appears.
标出活动路由
Identify the active route
虽然用户可以使用上一节中添加的链接来浏览你的应用,但他们并没有简单的方法来确定活动路由是什么。可以使用 Angular 的 routerLinkActive
指令添加这个功能。
While users can navigate your application using the links you added in the previous section, they don't have an easy way to identify what the active route is. You can add this functionality using Angular's routerLinkActive
directive.
在代码编辑器中,打开
app.component.html
文件。From your code editor, open the
app.component.html
file.更新 a 标签以包含
routerLinkActive
指令。Update the anchor tags to include the
routerLinkActive
directive.src/app/app.component.html <nav> <a class="button" routerLink="/crisis-list" routerLinkActive="activebutton">Crisis Center</a> | <a class="button" routerLink="/heroes-list" routerLinkActive="activebutton">Heroes</a> </nav>
再次查看你的申请表。单击其中一个按钮时,该按钮的样式会自动更新,并为该用户标出该活动组件。通过添加 routerLinkActive
指令,可以通知你的应用把一个特定的 CSS 类应用到当前的活动路由中。在本教程中,这个 CSS 类是 activebutton
,但你可以使用任何想要的类。
View your application again. As you click one of the buttons, the style for that button updates automatically, identifying the active component to the user. By adding the routerLinkActive
directive, you inform your application to apply a specific CSS class to the active route. In this tutorial, that CSS class is activebutton
, but you could use any class that you want.
添加一个重定向
Adding a redirect
在本教程的这一步中,你将添加一个重定向路由来把用户导向 /heroes-list
组件。
In this step of the tutorial, you add a route that redirects the user to display the /heroes-list
component.
在代码编辑器中,打开
app.module.ts
文件。From your code editor, open the
app.module.ts
file.在
imports
数组中,按如下所示更新RouterModule
部分。In the
imports
array, update theRouterModule
section as follows.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
属性替换成了这两个新属性:Notice that this new route uses an empty string as its path. In addition, it replaces the
component
property with two new ones:redirectTo
。这个属性指示 Angular 从空路径重定向到heroes-list
路径。redirectTo
. This property instructs Angular to redirect from an empty path to theheroes-list
path.pathMatch
。这个属性指示 Angular 要如何匹配 URL。对于本教程,你应该把这个属性设置为full
。当路径为空字符串时,建议使用此策略。有关此属性的更多信息,请参阅 Route API 文档。pathMatch
. This property instructs Angular on how much of the URL to match. For this tutorial, you should set this property tofull
. This strategy is recommended when you have an empty string for a path. For more information about this property, see the Route API documentation.
现在,当你打开应用时,它会默认显示 heroes-list
组件。
Now when you open your application, it displays the heroes-list
component by default.
添加 404 页面
Adding a 404 page
用户可以尝试访问你尚未定义的路由。为了解决这个问题,最佳做法是显示一个 404 页面。在本节中,你将创建一个 404 页面,并更新路由配置,以便为任何未指定的路由显示该页面。
It is possible for a user to try to access a route that you have not defined. To account for this behavior, a best practice is to display a 404 page. In this section, you'll create a 404 page and update your route configuration to show that page for any unspecified routes.
在终端上,创建一个新的组件
PageNotFound
。From the terminal, create a new component,
PageNotFound
.ng generate component page-not-found
在代码编辑器中,打开
page-not-found.component.html
文件并用下面的 HTML 替换它的内容。From your code editor, open the
page-not-found.component.html
file and replace its contents with the following 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
部分的内容。Open the
app.module.ts
file. In theimports
array, update theRouterModule
section as follows.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 表示通配符路由的方式。任何与你配置中的路由都不匹配的路由都会使用这个路由。The new route uses a path,
**
. This path is how Angular identifies a wildcard route. Any route that does not match an existing route in your configuration will use this route.请注意,通配符路由要放在数组的末尾。路由的顺序很重要,因为 Angular 会按顺序应用路由并使用所找到的第一个匹配项。
Notice that the wildcard route is placed at the end of the array. The order of your routes is important, as Angular applies routes in order and uses the first match it finds.
尝试导航到应用中不存在的路由,比如 http://localhost:4200/powers
。此路由与 app.module.ts
文件中定义的所有内容都不匹配。但是,由于你定义了一个通配符路由,该应用会自动显示你的 PageNotFound
组件。
Try navigating to a non-existing route on your application, such as http://localhost:4200/powers
. This route doesn't match anything defined in your app.module.ts
file. However, because you defined a wildcard route, the application automatically displays your PageNotFound
component.
下一步
Next steps
你已经有了一个基本的应用程序,它使用 Angular 的路由功能来根据 URL 地址改变用户可以看到的组件。你还扩展了这些特性,以包含一个重定向,以及一个用来显示自定义 404 页面的通配符路由。
At this point, you have a basic application that uses Angular's routing feature to change what components the user can see based on the URL address. You have extended these features to include a redirect, as well as a wildcard route to display a custom 404 page.
有关路由的更多信息,请参阅以下主题:
For more information about routing, see the following topics: