路由是 Angular 应用程序的核心,它加载与所请求路由相关联的组件,以及获取特定路由的相关数据。这允许我们通过控制不同的路由,获取不同的数据,从而渲染不同的页面。
接下来我们将按照以下目录的内容,介绍 Angular 的路由。具体目录如下:
目录
- Installing the router
- Base href
- Using the router
- RouterModule.forRoot
- RouterModule.forChild
- Configuring a route
- Displaying routes
- Futher configuration
- Dynamic routes
- Child routes
- Component-less routes
- loadChildren
- Router directives
- routerLink
- routerLinkActive
- Router API
Installing the router
首先第一件事,我们需要安装 Angular Router。你可以通过运行以下任一操作来执行此操作:
yarn add @angular/router # OR npm i --save @angular/router</div>
以上命令执行后,将会自动下载 @angular/router
模块到 node_modules
文件夹中。
Base href
我们需要做的最后一件事,是将 <base>
标签添加到我们的 index.html
文件中。路由需要根据这个来确定应用程序的根目录。例如,当我们转到 http://example.com/page1
时,如果我们没有定义应用程序的基础路径,路由将无法知道我们的应用的托管地址是 http://example.com
还是 http://example.com/page1
。
这件事操作起来很简单,只需打开项目中的 index.html 文件,添加相应的 <base> 标签,具体如下:
<!doctype html> <html> <head> <base href="/" rel="external nofollow" > <title>Application</title> </head> <body> <app-root></app-root> </body> </html></div>
以上配置信息告诉 Angular 路由,应用程序的根目录是 /
。
Using the router
要使用路由,我们需要在 AppModule
模块中,导入 RouterModule
。具体如下:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouterModule } from '@angular/router'; import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule, RouterModule ], bootstrap: [ AppComponent ], declarations: [ AppComponent ] }) export class AppModule {}</div>
此时我们的路由还不能正常工作,因为我们还未配置应用程序路由的相关信息。RouterModule
对象为我们提供了两个静态的方法:forRoot()
和 forChild()
来配置路由信息。
RouterModule.forRoot()
RouterModule.forRoot() 方法用于在主模块中定义主要的路由信息,通过调用该方法使得我们的主模块可以访问路由模块中定义的所有指令。接下来我们来看一下如何使用 forRoot()
:
// ... import { Routes, RouterModule } from '@angular/router'; export const ROUTES: Routes = []; @NgModule({ imports: [ BrowserModule, RouterModule.forRoot(ROUTES) ], // ... }) export class AppModule {}</div>
我们通过使用 const
定义路由的配置信息,然后把它作为参数调用 RouterModule.forRoot()
方法,而不是直接使用 RouterModule.forRoot([...])
这种方式,这样做的好处是方便我们在需要的时候导出 ROUTES
到其它模块中。
RouterModule.forChild()
RouterModule.forChild() 与 Router.forRoot() 方法类似,但它只能应用在特性模块中。
友情提示:根模块中使用 forRoot(),子模块中使用 forChild()
这个功能非常强大,因为我们不必在一个地方(我们的主模块)定义所有路由信息。反之,我们可以在特性模块中定义模块特有的路由信息,并在必要的时候将它们导入我们主模块。RouterModule.forChild()
的使用方法如下:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Routes, RouterModule } from '@angular/router'; export const ROUTES: Routes = []; @NgModule({ imports: [ CommonModule, RouterModule.forChild(ROUTES) ], // ... }) export class ChildModule {}</div>
通过以上示例,我们知道在主模块和特性模块中,路由配置对象的类型是一样的,区别只是主模块和特性模块中需调用不同的方法,来配置模块路由。接下来我们来介绍一下如何配置 ROUTES
对象。
Configuring a route
我们定义的所有路由都是作为 ROUTES
数组中的对象。首先,为我们的主页定义一个路由:
import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home/home.component'; export const ROUTES: Routes = [ { path: '', component: HomeComponent } ]; @NgModule({ imports: [ BrowserModule, RouterModule.forRoot(ROUTES) ], // ... }) export class AppModule {}</div>
示例中我们通过 path
属性定义路由的匹配路径,而 component
属性用于定义路由匹配时需要加载的组件。
友情提示:我们使用 path: ''
来匹配空的路径,例如:https://yourdomain.com
Displaying routes
配置完路由信息后,下一步是使用一个名为 router-outlet
的指令告诉 Angular 在哪里加载组件。当 Angular 路由匹配到响应路径,并成功找到需要加载的组件时,它将动态创建对应的组件,并将其作为兄弟元素,插入到 router-outlet
元素中。
在我们 AppComponent
组件中,我们可以在任意位置插入 router-outlet
指令:
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <div class="app"> <h3>Our app</h3> <router-outlet></router-outlet> </div> ` }) export class AppComponent {}</div>
我们现在已经建立了应用程序的主路由,我们可以进一步了解路由的其它配置选项。
Further configuration
到目前为止我们已经介绍的内容只是一个开始 ,接下来我们来看看其它一些选项和功能。
Dynamic routes
如果路由始终是静态的,那没有多大的用处。例如 path: ''
是加载我们 HomeComponent
组件的静态路由。我们将介绍动态路由,基于动态路由我们可以根据不同的路由参数,渲染不同的页面。
例如,如果我们想要在个人资料页面根据不同的用户名显示不同的用户信息,我们可以使用以下方式定义路由:
import { HomeComponent } from './home/home.component'; import { ProfileComponent } from './profile/profile.component'; export const ROUTES: Routes = [ { path: '', component: HomeComponent }, { path: '/profile/:username', component: ProfileComponent } ];</div>
这里的关键点是 :
,它告诉 Angular 路由,:username
是路由参数,而不是 URL 中实际的部分。
友情提示:如果没有使用 : ,它将作为静态路由,仅匹配 /profile/username 路径
现在我们已经建立一个动态路由,此时最重要的事情就是如何获取路由参数。要访问当前路由的相关信息,我们需要先从 @angular/router
模块中导入 ActivatedRoute
,然后在组件类的构造函数中注入该对象,最后通过订阅该对象的 params
属性,来获取路由参数,具体示例如下:
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/r