发表于: 2019-03-26 21:07:45
1 640
今天完成的事:
注册路由器与路由定义
要使用路由器,必须先注册来自 @angular/router
包中的 RouterModule
。 定义一个路由数组 appRoutes
并把它传给 RouterModule.forRoot()
方法。 它会返回一个模块,其中包含配置好的 Router
服务提供商,以及路由库所需的其它提供商。 一旦启动了应用,Router
就会根据当前的浏览器 URL 进行首次导航。
注意: RouterModule.forRoot
方法是用于注册全应用级提供商的编码模式。要详细了解全应用级提供商,参见单例服务 一章。
import { NgModule } from '@angular/core';import { BrowserModule } from '@angular/platform-browser';import { FormsModule } from '@angular/forms';import { RouterModule, Routes } from'@angular/router';import { AppComponent } from './app.component';import { CrisisListComponent } from './crisis-list/crisis-list.component';import { HeroListComponent } from './hero-list/hero-list.component';const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'heroes', component: HeroListComponent },];@NgModule({ imports: [ BrowserModule, FormsModule, RouterModule.forRoot( appRoutes, { enableTracing: true } // <-- debugging purposes only ) ], declarations: [ AppComponent, HeroListComponent, CrisisListComponent, ], bootstrap: [ AppComponent ]})export class AppModule { }
作为简单的路由配置,将添加配置好的 RouterModule
到 AppModule
中就足够了。 随着应用的成长,你将需要将路由配置重构到单独的文件中,并创建路由模块 - 一种特别的、专门为特性模块的路由器服务的服务模块。
把 RouterModule.forRoot()
注册到 AppModule
的 imports
中,能让该 Router
服务在应用的任何地方都能使用。
添加路由出口
根组件 AppComponent
是本应用的壳。它在顶部有一个标题、一个带两个链接的导航条,在底部有一个路由器出口,路由器会在它所指定的位置上把组件切入或调出页面。就像下图中所标出的:
路由出口扮演一个占位符的角色,路由组件将会渲染在它的下方。
该组件所对应的模板是这样的:
<h1>Angular Router</h1><nav> <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a> <arouterLink="/heroes" routerLinkActive="active">Heroes</a></nav><router-outlet></router-outlet>
定义通配符路由
你以前在应用中创建过两个路由,一个是 /crisis-center
,另一个是 /heroes
。 所有其它 URL 都会导致路由器抛出错误,并让应用崩溃。
可以添加一个通配符路由来拦截所有无效的 URL,并优雅的处理它们。 通配符路由的 path
是两个星号(**
),它会匹配任何 URL。 当路由器匹配不上以前定义的那些路由时,它就会选择这个路由。 通配符路由可以导航到自定义的“404 Not Found”组件,也可以重定向到一个现有路由。
路由器使用先匹配者优先的策略来选择路由。 通配符路由是路由配置中最没有特定性的那个,因此务必确保它是配置中的最后一个路由。
要测试本特性,请往 HeroListComponent
的模板中添加一个带 RouterLink
的按钮,并且把它的链接设置为 "/sidekicks"
。
<h2>HEROES</h2><p>Get your heroes here</p><button routerLink="/sidekicks">Go to sidekicks</button>
当用户点击该按钮时,应用就会失败,因为你尚未定义过 "/sidekicks"
路由。
不要添加 "/sidekicks"
路由,而是定义一个“通配符”路由,让它直接导航到 PageNotFoundComponent
组件。
{ path: '**', component: PageNotFoundComponent }
创建 PageNotFoundComponent
,以便在用户访问无效网址时显示它。
ng generate component page-not-found
<h2>Page not found</h2>
现在,当用户访问 /sidekicks
或任何无效的 URL 时,浏览器就会显示“Page not found”。 浏览器的地址栏仍指向无效的 URL。
设置跳转
应用启动时,浏览器地址栏中的初始 URL 是这样的:
localhost:4200
它不能匹配上任何具体的路由,于是就会走到通配符路由中去,并且显示 PageNotFoundComponent
。
这个应用需要一个有效的默认路由,在这里应该用英雄列表作为默认页。当用户点击"Heroes"链接或把 localhost:4200/heroes
粘贴到地址栏时,它应该导航到列表页。
首选方案是添加一个 redirect
路由来把最初的相对路径(''
)转换成期望的默认路径(/heroes
)。 浏览器地址栏会显示 .../heroes
,就像你直接导航到那里一样。
在通配符路由上方添加一个默认路由。 在下方的代码片段中,它出现在通配符路由的紧上方,展示了这个里程碑的完整 appRoutes
。
const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'heroes', component: HeroListComponent }, { path: '', redirectTo: '/heroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent }];
重定向路由需要一个 pathMatch
属性,来告诉路由器如何用 URL 去匹配路由的路径,否则路由器就会报错。 在本应用中,路由器应该只有在完整的 URL等于 ''
时才选择 HeroListComponent
组件,因此要把 pathMatch
设置为 'full'
。
从技术角度说,pathMatch = 'full'
导致 URL 中剩下的、未匹配的部分必须等于 ''
。 在这个例子中,跳转路由在一个顶级路由中,因此剩下的URL 和完整的URL 是一样的。
pathMatch
的另一个可能的值是 'prefix'
,它会告诉路由器:当剩下的URL 以这个跳转路由中的 prefix
值开头时,就会匹配上这个跳转路由。
在这里不能这么做!如果 pathMatch
的值是 'prefix'
,那么每个URL 都会匹配上 ''
。
尝试把它设置为 'prefix'
,然后点击 Go to sidekicks
按钮。别忘了,它是一个无效 URL,本应显示“Page not found”页。 但是,你仍然在“英雄列表”页中。在地址栏中输入一个无效的 URL,你又被路由到了 /heroes
。 每一个 URL,无论有效与否,都会匹配上这个路由定义。
默认路由应该只有在整个URL 等于 ''
时才重定向到 HeroListComponent
,别忘了把重定向路由设置为 pathMatch = 'full'
。
要了解更多,参见 Victor Savkin 的帖子关于重定向。
“起步阶段”总结
你得到了一个非常基本的、带导航的应用,当用户点击链接时,它能在两个视图之间切换。
你学到了如何:
加载路由库
往壳组件的模板中添加一个导航条,导航条中有一些 A 标签、
routerLink
指令和routerLinkActive
指令往壳组件的模板中添加一个
router-outlet
指令,视图将会被显示在那里用
RouterModule.forRoot
配置路由器模块设置路由器,使其合成 HTML5 模式的浏览器 URL
使用通配符路由来处理无效路由
当应用在空路径下启动时,导航到默认路由
这个初学者应用的结构是这样的:
angular-router-sample
src
app
crisis-list
crisis-list.component.css
crisis-list.component.html
crisis-list.component.ts
hero-list
hero-list.component.css
hero-list.component.html
hero-list.component.ts
page-not-found.component.css
page-not-found.component.html
page-not-found.component.ts
app.module.ts
main.ts
index.html
styles.css
tsconfig.json
node_modules ...
package.json
下面是当前里程碑中讨论过的文件列表:
<h1>Angular Router</h1><nav> <a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a> <arouterLink="/heroes" routerLinkActive="active">Heroes</a></nav><router-outlet></router-outlet>
里程碑 2:路由模块
在原始的路由配置中,你提供了仅有两个路由的简单配置来设置应用的路由。对于简单的路由,这没有问题。 随着应用的成长,你用到了更多路由器特性,比如守卫、解析器和子路由等,你会很自然地想要重构路由。 我们建议将路由信息移到一个单独的特殊用途的模块,叫做路由模块。
路由模块有一系列特性:
把路由这个关注点从其它应用类关注点中分离出去。
测试特性模块时,可以替换或移除路由模块。
为路由服务提供商(包括守卫和解析器等)提供一个共同的地方。
不要声明组件。
把路由集成到应用中
路由应用范例中默认不包含路由。 要想在使用 Angular CLI 创建项目时支持路由,请为项目或应用的每个 NgModule 设置 --routing
选项。 当你用 CLI 命令 ng new
创建新项目或用 ng generate app
命令创建新应用,请指定 --routing
选项。这会告诉 CLI 包含上 @angular/router
包,并创建一个名叫 app-routing.module.ts
的文件。 然后你就可以在添加到项目或应用中的任何 NgModule 中使用路由功能了。
比如,可以用下列命令生成带路由的 NgModule。
ng generate module my-module --routing
这将创建一个名叫 my-module-routing.module.ts
的独立文件,来保存这个 NgModule 的路由信息。 该文件包含一个空的 Routes
对象,你可以使用一些指向各个组件和 NgModule 的路由来填充该对象。
将路由配置重构为路由模块
在 /app
目录下创建一个 AppRouting
模块,以包含路由配置。
ng generate module app-routing --module app --flat
导入 CrisisListComponent
、HeroListComponent
和 PageNotFoundCompponent
组件,就像 app.module.ts
中那样。然后把 Router
的导入语句和路由配置以及 RouterModule.forRoot
移入这个路由模块中。
把 Angular 的 RouterModule
添加到该模块的 exports
数组中,以便再次导出它 。 通过再次导出 RouterModule
,当在 AppModule
中导入了 AppRoutingModule
之后,那些声明在 AppModule
中的组件就可以访问路由指令了,比如 RouterLink
和 RouterOutlet
。
做完这些之后,该文件变成了这样:
接下来,修改 app.module.ts
文件,从 imports
数组中移除 RouterModule.forRoot
。
本章稍后的部分,你将创建一个多路由模块,并揭示你为何必须以正确的顺序导入那些路由模块。
应用继续照常运行,你可以把路由模块作为将来每个模块维护路由配置的中心位置。
目标:
继续学习
问题:
进度慢
收获:
加油
继续学习
问题:
进度慢
收获:
加油
评论