RouterModule
RouterModule 是一个类,负责添加路由器指令和提供程序。
npm Package | @angular/router |
---|---|
Module | import { RouterModule } from'@angular/router'; |
Source | router/src/router_module.ts |
Overview
class RouterModule { static forRoot(routes: Routes,config?: ExtraOptions): ModuleWithProviders static forChild(routes: Routes): ModuleWithProviders }
How To Use
RouterModule可以导入多个,这就是为什么有两种方法来创建模块。
RouterModule.forRoot
创建一个包含所有指令,给定路由和路由器服务本身的模块。
RouterModule.forChil
创建一个包含所有指令和给定路由的模块,但不包括路由器服务。
在根模块注册时,应使用以下模块
@NgModule({ imports: [RouterModule.forRoot(ROUTES)] }) class MyNgModule {} /* ROUTES 是定义好了的路由配置信息常量 export const ROUTES=[{配置信息},{配置信息},{配置信息}] */
对于子模块和延迟加载的子模块,应使用以下模块:
@NgModule({ imports: [RouterModule.forChild(ROUTES)] }) class MyNgModule {}
要使用路由,我们需要在
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 {}此时我们的路由还不能正常工作,因为我们还未配置应用程序路由的相关信息。
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 {}我们通过使用
const
定义路由的配置信息,然后把它作为参数调用RouterModule.forRoot()
方法,而不是直接使用RouterModule.forRoot([...])
这种方式,这样做的好处是方便我们在需要的时候导出ROUTES
到其它模块中。
Description
管理状态转换是构建应用程序中最难的部分之一。
这在网络上尤其如此,您还需要确保状态被反映在URL中。
此外,我们经常希望将应用程序分解成多个捆绑包,并根据需要加载它们。
Angular router 解决了这些问题。
使用路由器,您可以声明性地指定应用程序状态,管理状态转换同时处理URL,并按需加载捆绑。
友情提示:根模块中使用
forRoot()
,子模块中使用forChild()
原文链接:https://www.f2er.com/angularjs/146261.htmlConfiguring 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,// ... }) export class AppModule {}示例中我们通过
path
属性定义路由的匹配路径,而component
属性用于定义路由匹配时需要加载的组件。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 {}我们现在已经建立了应用程序的主路由,我们可以进一步了解路由的其它配置选项。
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 } ];这里的关键点是
:
,它告诉 Angular 路由,:username
是路由参数,而不是 URL 中实际的部分。友情提示:如果没有使用
:
,它将作为静态路由,仅匹配/profile/username
路径现在我们已经建立一个动态路由,此时最重要的事情就是如何获取路由参数。要访问当前路由的相关信息,我们需要先从
@angular/router
模块中导入ActivatedRoute
,然后在组件类的构造函数中注入该对象,最后通过订阅该对象的params
属性,来获取路由参数,具体示例如下:import { Component,OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'profile-page',template: ` <div class="profile"> <h3>{{ username }}</h3> </div> ` }) export class SettingsComponent implements OnInit { username: string; constructor(private route: ActivatedRoute) {} ngOnInit() { this.route.params.subscribe((params) => this.username = params.username); } }介绍完动态路由,我们来探讨一下如何创建
child routes
。Child routes
实际上每个路由都支持子路由,假设在我们
/settings
设置页面下有/settings/profile
和/settings/password
两个页面,分别表示个人资料页和修改密码页。我们可能希望我们的
/ settings
页面拥有自己的组件,然后在设置页面组件中显示/ settings/profile
和/ settings/password
页面。我们可以这样做:import { SettingsComponent } from './settings/settings.component'; import { ProfileSettingsComponent } from './settings/profile/profile.component'; import { PasswordSettingsComponent } from './settings/password/password.component'; export const ROUTES: Routes = [ { path: 'settings',component: SettingsComponent,children: [ { path: 'profile',component: ProfileSettingsComponent },{ path: 'password',component: PasswordSettingsComponent } ] } ]; @NgModule({ imports: [ BrowserModule,}) export class AppModule {}在这里,我们在
setttings
路由中定义了两个子路由,它们将继承父路由的路径,因此修改密码页面的路由匹配地址是/settings/password
,依此类推。接下来,我们需要做的最后一件事是在我们的
SettingsComponent
组件中添加router-outlet
指令,因为我们要在设置页面中呈现子路由。如果我们没有在SettingsComponent
组件中添加router-outlet
指令,尽管/settings/password
匹配修改密码页面的路由地址,但修改密码页面将无法正常显示。具体代码如下:import { Component } from '@angular/core'; @Component({ selector: 'settings-page',template: ` <div class="settings"> <settings-header></settings-header> <settings-sidebar></settings-sidebar> <router-outlet></router-outlet> </div> ` }) export class SettingsComponent {}Component-less routes
另一个很有用的路由功能是
component-less
路由。使用component-less
路由允许我们将路由组合在一起,并让它们共享路由配置信息和 outlet。例如,我们可以定义
setttings
路由而不需要使用SettingsComponent
组件:import { ProfileSettingsComponent } from './settings/profile/profile.component'; import { PasswordSettingsComponent } from './settings/password/password.component'; export const ROUTES: Routes = [ { path: 'settings',}) export class AppModule {}此时,
/settings/profile
和/settings/password
路由定义的内容,将显示在AppComponent
组件的router-outlet
元素中。loadChildren
我们也可以告诉路由从另一个模块中获取子路由。这将我们谈论的两个想法联系在一起 - 我们可以指定另一个模块中定义的子路由,以及通过将这些子路由设置到特定的路径下,来充分利用
component-less
路由的功能。让我们创建一个
SettingsModule
模块,用来保存所有setttings
相关的路由信息:import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Routes,RouterModule } from '@angular/router'; export const ROUTES: Routes = [ { path: '',component: PasswordSettingsComponent } ] } ]; @NgModule({ imports: [ CommonModule,RouterModule.forChild(ROUTES) ],}) export class SettingsModule {}需要注意的是,在
SettingsModule
模块中我们使用forChild()
方法,因为SettingsModule
不是我们应用的主模块。另一个主要的区别是我们将
SettingsModule
模块的主路径设置为空路径 ('')。因为如果我们路径设置为/settings
,它将匹配/settings/settings
,很明显这不是我们想要的结果。通过指定一个空的路径,它就会匹配/settings
路径,这就是我们想要的结果。那么
/settings
路由信息,需要在哪里配置?答案是在AppModule
中。这时我们就需要用到loadChildren
属性,具体如下:export const ROUTES: Routes = [ { path: 'settings',loadChildren: './settings/settings.module#SettingsModule' } ]; @NgModule({ imports: [ BrowserModule,// ... }) export class AppModule {}需要注意的是,我们没有将
SettingsModule
导入到我们的AppModule
中,而是通过loadChildren
属性,告诉 Angular 路由依据loadChildren
属性配置的路径去加载SettingsModule
模块。这就是模块懒加载功能的具体应用,当用户访问/settings/**
路径的时候,才会加载对应的SettingsModule
模块,这减少了应用启动时加载资源的大小。另外我们传递一个字符串作为
loadChildren
的属性值,该字符串由三部分组成:
- 需要导入模块的相对路径
#
分隔符- 导出模块类的名称
了解完路由的一些高级选项和功能,接下来我们来介绍路由指令。
Router Directives
除了
router-outlet
指令,路由模块中还提供了一些其它指令。让我们来看看它们如何与我们之前介绍的内容结合使用。routerLink
为了让我们链接到已设置的路由,我们需要使用
routerLink
指令,具体示例如下:<nav> <a routerLink="/">Home</a> <a routerLink="/settings/password">Change password</a> <a routerLink="/settings/profile">Profile Settings</a> </nav>当我们点击以上的任意链接时,页面不会被重新加载。反之,我们的路径将在 URL 地址栏中显示,随后进行后续视图更新,以匹配
routerLink
中设置的值。如果我们想要链接到动态的路由地址,且该地址有一个
username
的路由变量,则我们可以按照以下方式配置routerLink
对应的属性值:<a [routerLink]="['/profile',username]"> Go to {{ username }}'s profile. </a>routerLinkActive
在实际开发中,我们需要让用户知道哪个路由处于激活状态,通常情况下我们通过向激活的链接添加一个 class 来实现该功能。为了解决上述问题,Angular 路由模块为我们提供了
routerLinkActive
指令,该指令的使用示例如下:<nav> <a routerLink="/settings" routerLinkActive="active">Home</a> <a routerLink="/settings/password" routerLinkActive="active">Change password</a> <a routerLink="/settings/profile" routerLinkActive="active">Profile Settings</a> </nav>通过使用
routerLinkActive
指令,当a
元素对应的路由处于激活状态时,active
类将会自动添加到a
元素上。最后,我们来简单介绍一下 Router API。
Router API
我们可以通过路由还提供的 API 实现与
routerLink
相同的功能。要使用 Router API,我们需要在组件类中注入Router
对象,具体如下:import { Component } from '@angular/core'; import { Router } from '@angular/router'; @Component({ selector: 'app-root',template: ` <div class="app"> <h3>Our app</h3> <router-outlet></router-outlet> </div> ` }) export class AppComponent { constructor(private router: Router) {} }组件类中注入的
router
对象中有一个navigate()
方法,该方法支持的参数类型与routerLink
指令一样,当调用该方法后,页面将会自动跳转到对应的路由地址。具体使用示例如下:import { Component,OnInit } from '@angular/core'; import { Router } from '@angular/router'; @Component({ selector: 'app-root',template: ` <div class="app"> <h3>Our app</h3> <router-outlet></router-outlet> </div> ` }) export class AppComponent implements OnInit { constructor(private router: Router) {} ngOnInit() { setTimeout(() => { this.router.navigate(['/settings']); },5000); } }若以上代码成功运行,用户界面将在 5 秒后被重定向到
/settings
页面。这个方法非常有用,例如当检测到用户尚未登录时,自动重定向到登录页面。import { Component,template: ` <div class="app"> <h3>Users</h3> <div *ngFor="let user of users"> <user-component [user]="user" (select)="handleSelect($event)"> </user-component> </div> <router-outlet></router-outlet> </div> ` }) export class AppComponent implements OnInit { users: Username[] = [ { name: 'toddmotto',id: 0 },{ name: 'travisbarker',id: 1 },{ name: 'tomdelonge',id: 2 } ]; constructor(private router: Router) {} handleSelect(event) { this.router.navigate(['/profile',event.name]); } }Angular 路由的功能非常强大,既可以使用指令方式也可以使用命令式 API,希望本文可以帮助你尽快入门,若要进一步了解路由详细信息,请访问 - Angular Router 官文文档。
我有话说
除了使用
navigate()
方法外还有没有其它方法可以实现页面导航?Angular Router API 为我们提供了
navigate()
和navigateByUrl()
方法来实现页面导航。那为什么会有两个不同的方法呢?使用
router.navigateByUrl()
方法与直接改变地址栏上的 URL 地址一样,我们使用了一个新的 URL 地址。然而router.navigate()
方法基于一系列输入参数,产生一个新的 URL 地址。为了更好的区分它们之间的差异,我们来看个例子,假设当前的 URL 地址是:/inBox/11/message/22(popup:compose)当我们调用
router.navigateByUrl('/inBox/33/message/44')
方法后,此时的 URL 地址将变成/inBox/33/message/44
。但如果我们是调用router.navigate('/inBox/33/message/44')
方法,当前的 URL 地址将变成/inBox/33/message/44(popup:compose)
。作者:semlinker 链接:http://www.jianshu.com/p/e72c79c6968e 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。