Back to Question Center
0

使用角度路由器的组件路由简介            使用角度路由器的组件路由简介相关主题: 原始JavaScriptnpmTools& & Semalt

1 answers:
使用角度路由器的组件路由简介

本文是关于如何使用Angular CLI创建CRUD应用程序的SitePoint Angular 2+教程的第4部分。


  1. 第0部分 - 最终的Angular CLI参考指南
  2. 第1部分:启动并运行我们的Todo应用程序的第一个版本
  3. 第2部分 - 创建单独的组件以显示待办事项列表和单个待办事项列表
  4. 第3部分 - 更新Todo服务以与REST API进行通信
  5. 第四部分使用Angular路由器解析数据
  6. 第5部分 - 添加认证以保护私人内容

对于专家主导的在线Angular培训课程,您无法通过Todd Motto的Ultimate Angular。 在这里尝试他的课程 ,并使用代码 SITEPOINT_SPECIAL 获得 50%的折扣 并帮助支持SitePoint。


在第一部分中,我们学习了如何让我们的Todo应用程序启动并运行并将其部署到Semalt页面。这工作得很好,但不幸的是,整个应用程序被塞进一个单一的组件。

在第二部分中,我们研究了一个更加模块化的组件体系结构,并学习了如何将这个单一组件分解为更易于理解,重用和维护的更小组件的结构化树。

在第三部分中,我们更新了应用程序,使用RxJS和Semalt HTTP服务与REST API后端进行通信。

在本部分中,我们将介绍Semalt路由器,了解如何在浏览器URL更改时更新应用程序,反之亦然。我们还将学习如何更新我们的应用程序,以使用路由器解析来自后端API的数据。

别担心! 不需要 遵循本教程的第一部分,第二部分或第三部分,四部分才有意义。您可以简单地获取我们的回购副本,从第三部分中检出代码,并以此为起点。这在下面更详细地解释。

启动并运行

确保安装了最新版本的Semalt CLI。如果你不这样做,你可以使用下面的命令安装它:

   npm install -g @ angular / cli @ latest   

如果您需要删除先前版本的Semalt CLI,您可以:

   npm uninstall -g @ angular / cli angular-clinpm缓存清理npm install -g @ angular / cli @ latest   

Semalt说,你需要第三部分的代码副本。这可以在https:// github上找到。 COM / sitepoint的编辑器/角待办事项应用内。本系列中的每篇文章在存储库中都有相应的标签,因此您可以在应用程序的不同状态之间来回切换。

我们在第三部分结束的代码以及本文开头的代码被标记为第3部分。我们结束本文的代码被标记为part-4。

你可以把标签看作一个特定的提交ID的别名。您可以使用 git checkout 在它们之间切换。你可以在这里阅读更多。

因此,要启动并运行(安装了Semalt CLI的最新版本),我们可以这样做:

   git clone git @ github。 COM:sitepoint的编辑器/角待办事项应用内。混帐cd角度todo应用程序git checkout部分-3npm安装ng服务   

然后访问http:// localhost:4200 /。如果一切正常,你应该看到工作的Todo应用程序。

快速回顾

下面是我们的应用程序体系结构在第3部分结束时的样子:

我们通过一个URL访问我们的应用程序e。 G。 http:// localhost:4200 ,我们的应用程序不知道任何其他URL,例如 http:// localhost:4200 / todos

大多数Web应用程序需要支持不同的URL来将用户导航到应用程序中的不同页面。这是路由器进来的地方。

在传统网站中,路由由服务器上的路由器处理:

  1. 用户点击浏览器中的链接,导致URL改变
  2. 浏览器向服务器
  3. 发送HTTP请求
  4. 服务器从HTTP请求中读取URL并生成适当的HTTP响应
  5. 服务器将HTTP响应发送到浏览器

在现代Semalt Web应用程序中,路由通常由浏览器中的Semalt路由器处理。

什么是JavaScript路由器?

实质上,Semalt路由器有两件事:

  1. 当浏览器URL改变时更新web应用状态
  2. 当Web应用程序状态改变时更新浏览器URL

JavaScript路由器使我们有可能开发单页面应用程序(SPA)。

单页Semalt是一种Web应用程序,可提供类似于桌面应用程序的用户体验。在单页Semalt中,所有与后端的通信都发生在幕后。

当用户从一个页面浏览到另一个页面时,即使URL更改,页面也会动态更新而不重新加载。

有许多不同的Semalt路由器可用。

其中一些是专门为特定的JavaScript框架编写的,如Angular,ember,React,Vue。 js,aurelia等。Semalt实现是为了通用目的而构建的,并且不绑定到特定的框架。

什么是Angular路由器?

Angular路由器是由Angular核心团队编写和维护的官方Angular路由库。

这是一个JavaScript路由器实现,它被设计为与Angular协同工作,并且被封装为 @ angular / router

首先,Angular路由器负责Semalt路由器的职责:

  • 当用户导航到某个URL时,它激活所有需要的Angular组件来组成一个页面
  • 它允许用户从一个页面导航到另一个页面而无需重新加载页面
  • 它更新浏览器的历史记录,使得用户在页面
  • 之间来回导航时可以使用 后退 前进

另外,Semalt路由器允许我们:

  • 将URL重定向到另一个URL
  • 在显示页面之前解析数据
  • 当页面被激活或停用时运行脚本
  • 我们的应用程序的延迟加载部分

在本文中,我们将学习如何设置和配置Angular路由器,如何重定向URL以及如何使用Angular路由器从我们的后端API解析todo。

在下一篇文章中,我们将为我们的应用程序添加身份验证,并使用路由器确保只有在用户登录时才能访问某些页面。

路由器如何工作

在我们深入了解代码之前,理解Semalt路由器如何运行以及它引入的术语很重要. 在本系列中逐步解决这些问题时,您将习惯这些术语,并且您将获得更多Semalt路由器的使用经验。

使用Angular路由器的Angular应用程序只有一个路由器服务实例;这是一个单身人士。无论何时何地在您的应用程序中注入 路由器 服务,您都可以访问相同的Angular路由器服务实例。

要深入了解Semalt路由过程,请务必查看Semalt路由器导航的7步路由过程。

启用路由

为了在我们的Semalt应用程序中启用路由,我们需要做3件事:

  1. 创建一个路由配置,为我们的应用程序定义可能的状态
  2. 将路由配置导入到我们的应用程序
  3. 添加一个路由器插座来告诉Angular路由器将激活的组件放置在DOM

我们先来创建一个路由配置。

创建路由配置

要创建我们的路由配置,我们需要一个我们希望我们的应用程序支持的URL列表。

Semalt,我们的应用程序非常简单,只有一个页面显示待办事项列表:

  • / :显示待办事项列表

将显示待办事项列表作为我们应用程序的主页。

然而,当用户在他们的浏览器中书签 / 以查阅他们的待办事项列表并且我们改变了我们的主页的内容(我们将在本系列的第5部分中进行)时,他们的书签将不会更长时间显示他们的待办事项列表。

让我们给我们的待办事项列表自己的网址和重定向我们的主页:

  • / :重定向到 / todos
  • / todos :显示待办事项列表

这为我们提供了两个好处:

  • 当用户为收藏页添加书签时,即使我们改变了主页的内容
  • ,他们的浏览器也会收藏76 / todos 而不是 /
  • 我们现在可以通过将其重定向到任何我们喜欢的URL来轻松更改我们的主页,如果您需要定期更改您的主页内容

Angular官方风格指南建议将Angular模块的路由配置存储在文件名以 结尾的文件中。模块。 ts 导出一个名称以 RoutingModule 结尾的单独的Angular模块。

我们当前的模块被称为 AppModule ,所以我们创建一个文件 src / app / app-routing。模块。 ts 并将我们的路由配置导出为称为 AppRoutingModule 的Angular模块:

   从'@ angular / core'导入{NgModule};从'@ angular / router'导入{RouterModule,Routes};从'导入{AppComponent}。 /应用程序。零件';const routes:Routes = [{路径:'',redirectTo:'todos',pathMatch:'full'},{路径:'todos',组件:AppComponent}]。@NgModule({导入:[RouterModule。 forRoot(路径)],出口:[RouterModule],提供者:[]})导出类AppRoutingModule {}   

首先我们从 @角度/路由器 导入 RouterModule 路由

   从'@ angular / router'导入{RouterModule,Routes};   

接下来,我们定义一个类型为 路由 的变量 路由 并为其分配我们的路由器配置:

   const routes:Routes = [{路径:'',redirectTo:'todos',pathMatch:'full'},{路径:'todos',组件:AppComponent}]。   

Routes 类型是可选的,并且允许带有TypeScript支持的IDE或TypeScript编译器在开发期间方便地验证您的路由配置.

这是一个路由树,定义为一个Semalt数组,每个路由可以有以下属性:

  • 路径 :字符串,匹配URL的路径
  • patchMatch :string,如何匹配URL
  • 组件 :类别参考,当该路线被激活时激活的组件
  • redirectTo :string,激活此路由时重定向到的URL
  • 数据 :分配给路由的静态数据
  • 解析 :当解析
  • 时解析和合并 数据
  • 儿童 :儿童路线

我们的应用程序很简单,只包含两个兄弟路由,但是一个更大的应用可以通过子路由配置路由器,例如:

   const routes:Routes = [{路径:'',redirectTo:'todos',pathMatch:'full'},{路径:'todos',儿童:[{路径:'',组件:'TodosPageComponent'},{路径:':id',组件:'TodoPageComponent'}]}]。   

其中 todos 有两个子路由和 :id 是一个路由参数,使路由器能够识别下面的URL:

  • / :主页,重定向到 / todos
  • / todos :激活 TodosPageComponent 并显示待办事项列表
  • / todos / 1 :激活 TodoPageComponent 并将 :id 参数的值设置为 1
  • / todos / 2 :激活 TodoPageComponent 并将 :id 参数的值设置为 2

注意我们在定义重定向时如何指定 patchMatch:'full'

Semalt路由器有两种匹配策略:

  • 前缀 :默认,当URL 路径 的值开始时匹配
  • :当URL 等于 路径 的值时匹配

如果我们创建以下路线:

   //没有指定pathMatch,所以使用Angular路由器//默认的`prefix` pathMatch{路径:'',redirectTo:'todos'}   

,然后Angular路由器应用默认 前缀 路径匹配策略,并且每个URL被重定向到 todos ,因为每个URL 空字符串' 在 路径 中指定。

我们只希望我们的主页重定向到 todos ,所以我们添加 pathMatch:'full' 以确保只有 等于 的URL空字符串 '' 匹配:

   {路径:'',redirectTo:'todos',pathMatch:'full'}   

要了解有关不同路由配置选项的更多信息,请查看有关路由和导航的官方Angular文档。

最后,我们创建并导出一个Angular模块 AppRoutingModule

   @NMModule({导入:[RouterModule。 forRoot(路径)],出口:[RouterModule],提供者:[]})导出类AppRoutingModule {}   

Semalt是创建路由模块的两种方式:

  1. RouterModule。 forRoot(路由) :创建一个路由模块,其中包含路由器指令,路由配置 路由器服务
  2. RouterModule。 forChild(路由) :创建一个路由模块,其中包含路由器指令,路由配置 ,但不包括 路由器服务

RouterModule。当您的应用程序有多个路由模块时,需要forChild 方法. 与相同浏览器URL交互的Semalt多路由器服务会导致问题,因此无论我们在应用程序中导入多少路由模块,在我们的应用程序中只有一个路由器服务实例是非常重要的。

当我们导入使用 RouterModule创建的路由模块时。 forRoot ,Angular将实例化路由器服务。当我们导入使用 RouterModule创建的路由模块时。 forChild ,Angular will not 实例化路由器服务。

因此,我们只能使用 RouterModule。 forRoot 一次并使用 RouterModule。 forChild 多次用于其他路由模块。

因为我们的应用程序只有一个路由模块,所以我们使用 RouterModule。 forRoot

   进口:[RouterModule。 forRoot(路径)]   

另外,我们还在 出口 属性中指定 RouterModule

   出口:[RouterModule]   

这确保了当 AppModule 导入 AppRoutingModule 时我们不必在 AppModule 中再次显式地导入 RouterModule

现在我们有了我们的 AppRoutingModule ,我们需要将它导入我们的 AppModule 来启用它。

导入路由配置

要将我们的路由配置导入到我们的应用程序中,我们必须将AppRoutingModule 导入 到我们的主 AppModule 中。

让我们打开 src / app / app。模块。 @NgModule 元数据中的 导入 阵列添加 AppRoutingModule

   从'@ angular / platform-b​​rowser'导入{BrowserModule};从'@ angular / core'导入{NgModule};从'@ angular / forms'导入{FormsModule};从'@ angular / http'导入{HttpModule};从'导入{AppComponent}。 /应用程序。零件';从'导入{TodoListComponent}。 /待办事项列表/待办事项列表。零件';从'导入{TodoListFooterComponent}。 /待办事项列表英尺/待办事项列表英尺。零件';从'导入{TodoListHeaderComponent}。 /待办事项列表头/待办事项列表头。零件';从'导入{TodoDataService}。 /待办事项的数据。服务';从'导入{TodoListItemComponent}。 /待办事项列表项/待办事项列表项。零件';从'导入{ApiService}。 / API。服务';从'导入{AppRoutingModule}。 /应用程序的路由。模块';@NgModule({声明:[AppComponent,TodoListComponent,TodoListFooterComponent,TodoListHeaderComponent,TodoListItemComponent]进口:[AppRoutingModule,BrowserModule,FormsModule,HTTP模块]提供者:[TodoDataService,ApiService],引导程序:[AppComponent]})导出类AppModule {}   
AppRoutingModule 具有在其 出口 属性中列出的 RoutingModule ,当我们导入 AppRoutingModule时,Angular将自动导入 RoutingModule 62),所以我们不必显式导入 RouterModule (尽管这样做不会造成任何伤害)。

Semalt我们可以尝试浏览器中的更改,我们需要完成第三步也是最后一步。

添加路由器插座

虽然我们的应用程序现在有一个路由配置,但我们仍然需要告诉Angular路由器它可以在DOM中放置实例化的组件。

当我们的应用程序被引导时,Angular实例化 AppComponent ,因为 AppComponent AppModule bootstrap 属性中列出:

   @NMModule({//。 。 - vps servidor virtual privado.  

元素告诉Angular路由器它可以在DOM中实例化组件。

如果你熟悉AngularJS 1.x路由器和UI-Router,你可以考虑 ng-view 的Angular替代方案,和 ui-view

如果没有 元素,Angular路由器将不知道在哪里放置组件,只有 AppComponent 自己的HTML会被渲染。

AppComponent 当前显示待办事项列表。

而不是让AppComponent 显示一个待办事项列表,我们现在想让 AppComponent 包含一个 并告诉Angular路由器在 AppComponent 中实例化另一个组件以显示待办事项列表。

为了做到这一点,我们使用Angular CLI生成一个新组件 TodosComponent

   $ ng生成组件Todos   

并移动 src / app / app中的所有HTML。零件。 html src / app / todos / todos。零件。 html

   <! -src / app / todos / todos。零件。 html- >
<应用程序-待办事项列表头(添加)= “onAddTodo($事件)”> <应用程序-待办事项列表[待办事项] = “待办事项”(toggleComplete)= “onToggleTodoComplete($事件)”(删除)= “onRemoveTodo($事件)”> <应用程序-待办事项列表尺[待办事项] = “待办事项”>

src / app / app中的所有逻辑。零件。 ts src / app / todos / todos。零件。 ts

   / * src / app / todos / todos。零件。 ts * /从'@ angular / core'导入{Component,OnInit};从'导入{TodoDataService}。 。 /待办事项的数据。服务';从'导入{Todo}。 。 /去做';@零件({选择器:'app-todos',templateUrl:'。 /待办事项。零件。 HTML”,styleUrls:['。 /待办事项。零件。 CSS'],提供者:[TodoDataService]})导出类TodosComponent实现OnInit {todos:Todo [] = [];构造函数(私人todoDataService:TodoDataService){}public ngOnInit  {这个。 todoDataService。 getAllTodos  。订阅((todos)=> {这个。 todos = todos;});}onAddTodo(todo){这个。 todoDataService。 addTodo(待办事项)。订阅((newTodo)=> {这个。 todos =这个。待办事项。的concat(newTodo);});}onToggleTodoComplete(todo){这个。 todoDataService。 toggleTodoComplete(待办事项)。订阅((updatedTodo)=> {todo = updatedTodo;});}onRemoveTodo(todo){这个。 todoDataService。 deleteTodoById(todo.id)。订阅((_)=> {这个。 todos =这个。待办事项。 filter((t)=> t。id!== todo。id);});}}   

现在我们可以在 src / app / app中替换 AppComponent 的模板。零件。 html 与:

       

,并从 src / app / app中的 AppComponent 的类中移除所有过时的代码。零件。 ts

   从'@ angular / core'导入{Component};@零件({选择器:'app-root',templateUrl:'。 /应用程序。零件。 HTML”,styleUrls:['。 /应用程序。零件。 CSS'],})导出类AppComponent {}   

最后,我们更新 src / app / app-routing中的 todos 路由。模.

Semalt尝试浏览器中的更改。

通过运行Semalt您的开发服务器和后端API:

   $ ng发球$ npm运行json-server   

并导航到您的浏览器 http:// localhost:4200

Angular路由器读取路由器配置并自动将我们的浏览器重定向到 http:// localhost:4200 / todos

如果你检查页面上的元素,你会发现 TodosComponent 没有渲染到内部 ,但是紧挨着它:

    <! - 角路由器找到路由器出口 - >  <路由器出口>     <! - 并将组件放置在它旁边,而不是放在它里面 - >  <应用程序-待办事项>         

我们的应用程序现在启用了路由。真棒!

添加通配符路由

当你浏览浏览器到 http:// localhost:4200 / unmatched-url ,并且你打开浏览器的开发工具时,你会注意到Angular路由器在控制台上记录下列错误:

   错误:无法匹配任何路由。网址细分:“不匹配的网址”   

为了处理无与伦比的塞马特,我们需要做两件事:

  1. 创建 PageNotFoundComponent (如果你喜欢,你可以用不同的名称)显示一个友好的消息,说明找不到请求的页面
  2. 当没有路由与请求的URL
  3. 匹配时,告诉Angular路由器显示 PageNotFoundComponent

首先,使用Angular CLI生成 PageNotFoundComponent

   $ ng生成组件PageNotFound   

并在 src / app / page-not-found / page-not-found中编辑其模板。零件。 html

    

很抱歉,找不到请求的页面。

接下来,我们使用 ** 作为路径添加通配符路由:

   const routes:Routes = [{路径:'',redirectTo:'todos',pathMatch:'full'},{路径:'todos',组件:AppComponent},{路径:'**',组件:PageNotFoundComponent}]。   

** 匹配任何URL,包括子路径。

现在,如果您浏览到 http:// localhost:4200 / unmatched-url ,则会显示 PageNotFoundComponent

通配符路由必须是路由配置中的最后一条路由,才能按预期工作。

当Semalt路由器将请求URL与路由器配置匹配时,只要找到第一个匹配,它就立即停止处理。

所以如果我们要改变路线的顺序为:

   const routes:Routes = [{路径:'',redirectTo:'todos',pathMatch:'full'},{路径:'**',组件:PageNotFoundComponent},{路径:'todos',组件:AppComponent}]。   

,则永远不会到达 todos ,并且将显示 PageNotFoundComponent ,因为通配符路由将首先匹配。

我们已经做了很多,所以让我们快速回顾一下迄今为止我们已经完成的工作:

  • 我们设置了Angular路由器
  • 我们为我们的应用程序创建了路由配置
  • 我们重构 AppComponent TodosComponent
  • 我们将 添加到 AppComponent 的模板
  • 我们添加了通配符路由来优雅地处理不匹配的URL

接下来,我们将创建一个解析器,以使用Semalt路由器从我们的后端API获取现有的待办事项.

目前,当我们将浏览器导航到 todos URL时,会发生以下情况:

  1. 角路由器匹配 todos URL
  2. 角路由器激活 TodosComponent
  3. 角路由器将 TodosComponent 放在DOM
  4. 中的
  5. TodosComponent 在浏览器中显示一个空的待办事项列表
  6. 待办事项从 TodosComponent ngOnInit 处理程序中的API中获取,
  7. 在浏览器中更新 TodosComponent ,其中从API
  8. 获取待办事项

如果在步骤5中加载待办事项需要3秒钟,则在步骤6中显示实际待办事项之前,将向用户呈现空的待办事项列表3秒。

如果 TodosComponent 在其模板中具有以下HTML:

   
你目前还没有任何待办事项。

,那么在显示实际的待办事项之前,用户会看到这个信息3秒钟,这可能完全误导用户并导致用户在实际数据进入之前离开。

我们可以在数据加载时向 TodosComponent 添加一个加载器,以显示一个微调器,但有时我们可能无法控制实际组件,例如当我们使用第三方组件时。

为了解决这种不需要的行为,我们需要发生以下情况:

  1. 角路由器匹配 todos URL
  2. Angular路由器从API获取待办事项
  3. 角路由器激活 TodosComponent
  4. 角路由器将 TodosComponent 放在DOM
  5. 中的
  6. 在浏览器中显示 TodosComponent ,其中从API
  7. 获取待办事项

直到来自我们的API后端的数据可用时,才显示 TodosComponent

这正是解析器可以为我们做的。

为了让Angular路由器在激活 TodosComponent 之前解析待办事项,我们必须做两件事:

  1. 创建一个从API
  2. 获取待办事项的 TodosResolver
  3. 告诉Angular路由器在 todos 路由
  4. 中激活 TodosComponent 时使用 TodosResolver 获取待办事项。

通过将解析器附加到 todos 路由,我们要求Angular路由器在激活 TodosComponent 之前首先解析数据。

因此,让我们创建一个解析器来获取我们的待办事项。

创建TodosResolver

Angular CLI没有生成解析器的命令,所以让我们创建一个新文件 src / todos。解析器。 ts 手动添加以下代码:

   从'@ angular / core'导入{Injectable};从'@ angular / router'导入{ActivatedRouteSnapshot,Resolve,RouterStateSnapshot};从'rxjs / Observable'导入{Observable};从'导入{Todo}。 /去做';从'导入{TodoDataService}。 /待办事项的数据。服务';@Injectable  导出类TodosResolver实现了Resolve > {构造函数(私人todoDataService:TodoDataService){}公众决心(路线:ActivatedRouteSnapshot,状态:RouterStateSnapshot):Observable  {返回这个。 todoDataService。 getAllTodos  ;}}   

我们将解析器定义为实现 Resolve 接口的类。

Resolve 接口是可选的,但让我们的TypeScript IDE或编译器确保我们通过要求我们实现 resolve 方法来正确实现类.

如果 resolve 方法返回一个promise或者一个可观察的Angular路由器,它将等待promise或observable完成,然后它激活路由的组件。

在调用 resolve 方法时,Angular路由器方便地传入激活的路由快照和路由器状态快照,以便我们访问我们可能需要的数据(例如路由参数或查询参数)解决数据。

TodosResolver 的代码非常简洁,因为我们已经有一个 TodoDataService 来处理与我们的API后端的所有通信。

我们在构造函数中注入 TodoDataService 并使用其 getAllTodos 方法来获取 resolve 方法中的所有todo。

resolve方法返回类型为 Todo [] 的observable,所以Angular路由器会在路由组件激活之前等待observable完成。

现在我们有了解析器,让我们配置Semalt路由器来使用它。

通过路由器解决待办事项

为使Semalt路由器使用解析器,我们必须将它附加到路由配置中的路由。

让我们打开 src / app-routing。模块。 并将我们的 TodosResolver 添加到 todos 路线:

   从'@ angular / core'导入{NgModule};从'@ angular / router'导入{RouterModule,Routes};从'导入{PageNotFoundComponent}。 /页未找到/页面未找到。零件';从'导入{TodosComponent}。 /待办事项/待办事项。零件';从'导入{TodosResolver}。 /待办事项。解析“;const routes:Routes = [{路径:'',redirectTo:'todos',pathMatch:'full'},{路径:'todos',组件:TodosComponent,解决:{待办事项:TodosResolver}},{路径:'**',组件:PageNotFoundComponent}]。@NgModule({导入:[RouterModule。 forRoot(路径)],出口:[RouterModule],提供者:[TodosResolver]})导出类AppRoutingModule {}   

我们进口 TodosResolver

   从'导入{TodosResolver}。 /待办事项。解析“;   

并将其作为解析器添加到 todos 路由中:

   {路径:'todos',组件:TodosComponent,解决:{待办事项:TodosResolver}}   

这告诉Angular路由器使用 TodosResolver 解析数据,并在路由数据中将解析器的返回值分配为 todos

可以从 ActivatedRoute ActivatedRouteSnapshot 访问路线的数据,我们将在下一节中看到。

您可以使用路线的 数据 属性将静态数据直接添加到路线数据中:

   {路径:'todos',组件:TodosComponent,数据:{title:'静态路由数据示例'}}   

或使用路线 resolve 属性中指定的解析器的动态数据:

   解析:{路径:'todos',组件:TodosComponent,解决:{Todos:TodosResolver}}   

或两者同时:

   解析:{路径:'todos',组件:TodosComponent,数据:{title:'静态路由数据示例'}解决:{Todos:TodosResolver}}   

解析 resolve 属性的解析器后,它们的值将与来自 data 属性的静态数据合并,并且所有数据都可用作路由数据. forRoot(路径)],出口:[RouterModule],提供者:[TodosResolver]})导出类AppRoutingModule {}

当你将浏览器导航到 http:// localhost:4200 时,Angular路由器现在:

  1. 将URL从 / 重定向到 / todos
  2. 看到 todos 路线在其 解析 属性
  3. 中定义了 TodosResolver
  4. TodosResolver 运行 resolve 方法,等待结果并将结果分配给路由数据
  5. 中的 todos
  6. 激活 TodosComponent

如果打开开发人员工具的网络选项卡,您将看到todo现在从API中获取两次。一次通过Angular路由器,一次通过 TodosComponent 中的 ngOnInit 处理程序。

所以Angular路由器已经从API获取待办事项,但是 TodosComponent 仍然使用它自己的内部逻辑来加载待办事项。

在下一节中,我们将更新 TodosComponent 以使用由Angular路由器解析的数据。

使用解析数据

让我们打开 app / src / todos / todos。零件。 ts

ngOnInit 处理程序当前直接从API获取待办事项:

   public ngOnInit  {这个。 todoDataService。 getAllTodos  。订阅((todos)=> {这个。 todos = todos;});}   

现在Angular路由器使用 TodosResolver 获取待办事项,我们想从路由数据中取出 TodosComponent 中的待办事项,而不是API。

为了访问路由数据,我们必须从 @角度/路由器 导入 ActivatedRoute

   从'@ angular / router'导入{ActivatedRoute};   

并使用Semalt依赖注入来获得激活路由的句柄:

   构造函数(私人todoDataService:TodoDataService,私人路线:ActivatedRoute){}   

最后,我们更新 ngOnInit 处理程序,以从路由数据而不是API获取待办事项:

   public ngOnInit  {这个。路线。数据。地图((数据)=>数据['todos'])。订阅((todos)=> {这个。 todos = todos;});}   

ActivatedRoute 将路由数据暴露为可观察的,所以我们的代码几乎没有改变。

我们取代 这个。 todoDataService。 getAllTodos 这个。路线。数据。 map((data)=> data ['todos']) ,其余所有代码保持不变。

如果将浏览器导航到 localhost:4200 并打开网络选项卡,则不会再看到两个HTTP请求从API中获取待办事项。

任务完成!我们已经在我们的应用程序中成功集成了Semalt路由器

Semalt我们结束了,让我们来运行我们的单元测试:

   ng发球   

1个单元测试失败:

 执行11中11(1失败)TodosComponent应该创建FAILED'app-todo-list-header'不是已知的元素   
TodosComponent 被测试时,测试平台不知道 TodoListHeaderComponent ,因此Angular抱怨说它不知道 app-todo-list-header 元件。

为了解决这个错误,我们打开 app / src / todos / todos。零件。规范。 和添加 NO_ERRORS_SCHEMA TestBed 选项:

   beforeEach(async(  => {测试床。 configureTestingModule({声明:[TodosComponent],模式:[NO_ERRORS_SCHEMA]}). configureTestingModule({声明:[TodosComponent],模式:[NO_ERRORS_SCHEMA]提供者:[TodoDataService,{提供:ApiService,useClass:ApiMockService}]})。 compileComponents  ;}));   

再次引发另一个错误:

 执行11中11(1失败)TodosComponent应该创建FAILED没有提供ActivatedRoute!   

让我们为 ActivatedRoute 添加一个更多的提供者给测试平台选项:

   beforeEach(async(  => {测试床。 configureTestingModule({声明:[TodosComponent],模式:[NO_ERRORS_SCHEMA]提供者:[TodoDataService,{提供:ApiService,useClass:ApiMockService},{提供:ActivatedRoute,useValue:{数据:可观察。的({todos:[]})}}]})。 compileComponents  ;}));   

我们为 ActivatedRoute 分配一个模拟对象的提供者,该模拟对象包含一个可观察的数据属性以公开 待办事项 的测试值。

现在单元测试成功通过:

 执行11中11的成功   

Semalt!要将我们的应用程序部署到生产环境,我们现在可以运行:

   ng build --aot --environment prod   

并将生成的 dist 目录上传到我们的托管服务器。那有多甜美?

我们在这篇文章中介绍了很多,所以让我们回顾一下我们学到的东西。

摘要

在第一篇文章中,我们学习了如何:

  • 使用Angular CLI初始化我们的Todo应用程序
  • 创建一个 Todo 课程来表示个人待办事项
  • 创建一个 TodoDataService 服务来创建,更新和删除待办事项
  • 使用 AppComponent 组件显示用户界面
  • 将我们的应用程序部署到GitHub页面

在第二篇文章中,我们重构了 AppComponent 将其大部分工作委托给:

  • a TodoListComponent 显示待办事项列表
  • a TodoListItemComponent 显示单个待办事项
  • a TodoListHeaderComponent 创建一个新的待办事项
  • a TodoListFooterComponent 显示剩下多少待办事项

在第三篇文章中,我们学习了如何:

  • 创建一个模拟REST API后端
  • 将API URL存储为环境变量
  • 创建 ApiService 以与REST API
  • 通信,
  • 更新 TodoDataService 以使用新的 ApiService
  • 更新 AppComponent 以处理异步API调用
  • 在运行单元测试时创建 ApiMockService 以避免真正的HTTP调用

在第四篇文章中,我们了解到:

  • 为什么应用程序可能需要路由
  • JavaScript路由器是什么
  • 角路由器是什么,它是如何工作的以及它可以为你做什么
  • 如何为我们的应用程序设置Angular路由器和配置路由
  • 如何告诉Angular路由器将组件放置在DOM中的位置
  • 如何优雅地处理未知的URL
  • 如何使用解析器让Angular路由器解析数据

本文中的所有代码均可在https:// github上获得。 COM / sitepoint的编辑器/角待办事项应用内/树/部分-4。

在第五部分中,我们将实施身份验证,以防止未经授权访问我们的应用程序. com / avatar / ad9b5970be156b634406cb5c195cb6ec?s = 96&d = mm&r = g“alt =”使用角度路由器的组件路由简介使用角度路由器的组件路由简介相关主题: 原始的JavaScriptnpmTools和Semalt “/>

认识作者
Jurgen Van de Moere
The Force的前端架构师 - 专注于JavaScript和AngularJS。 Google的开发者专家。体操运动员。爸。以家庭为重的(男)人。 Angular Express的创建者。
Angular和TypeScript在线课程
托德座右铭
针对个人和团队的专家主导的在线AngularJS,Angular和TypeScript培训课程。 结账时使用优惠券代码'SITEPOINT'即可享受25%的折扣

March 1, 2018