官网:https://angular.io/api/router/RouterOutlet#description

Acts as a placeholder that Angular dynamically fills based on the current router state.

RouterOutlet作为place holder,Angular会基于当前路由状态动态地填充内容进来。

使用的selector正是router-outlet. 如下图第60行代码所示。

Each outlet can have a unique name, determined by the optional name attribute. The name cannot be set or changed dynamically. If not set, default value is “primary”.

每个router-outlet可以分配一个name,默认的名称是primary.

<router-outlet></router-outlet>
<router-outlet name='left'></router-outlet>
<router-outlet name='right'></router-outlet>

A router outlet emits an activate event when a new component is instantiated, and a deactivate event when a component is destroyed.

当一个新的Component被实例化时,routerOutlet 会发送一个activate事件。应用程序可以监听这个事件。

<router-outlet(activate)='onActivate($event)'(deactivate)='onDeactivate($event)'></router-outlet>

路由配置对象: Route Object

Each definition translates to a Route object which has two things: a path, the URL path segment for this route; and a component, the component associated with this route.

The router draws upon its registry of definitions when the browser URL changes or when application code tells the router to navigate along a route path.

当浏览器的url发生变化,或者应用程序调用router的路由方法时,Angular router就根据这些注册的定义,进行新Component的绘制。

When the browser’s location URL changes to match the path segment /XXX, then the router activates an instance of the YComponent and displays its view.

例如,当浏览器地址栏的url变成/XXX时,router激活XXX对应的Component Y的一个实例,然后显示其视图。

In order to use the Router, you must first register the RouterModule from the @angular/router package.

要使用Angular 路由功能,必须先从@angular/router包里导入RouterModule:

Define an array of routes, appRoutes, and pass them to the RouterModule.forRoot() method.

定义一个包含路由信息的数组,传入RouterModule.forRoot方法里。

The RouterModule.forRoot() method returns a module that contains the configured Router service provider, plus other providers that the routing library requires.

RouterModule.forRoot方法返回一个新的module,包含了配置好的Router service provider,加上其他路由库实现需要的provider.

You might have noticed that the CLI adds RouterModule.forRoot(routes) to the AppRoutingModule imports array. This lets Angular know that the AppRoutingModule is a routing module and forRoot() specifies that this is the root routing module. It configures all the routes you pass to it, gives you access to the router directives, and registers the Router service. Use forRoot() only once in the application, inside the AppRoutingModule.

Once the application is bootstrapped, the Router performs the initial navigation based on the current browser URL.

当Angular应用完成初始化之后,Router基于当前浏览器的默认url,进行初始跳转动作。

RouterModule provides the Router service, as well as router directives, such as RouterOutlet and routerLink.

RouterModule提供Router服务,Router directive,比如RouterOutlet和RouterLink.

The root application module imports RouterModule so that the application has a Router and the root application components can access the router directives.

Root应用module导入RouterModule,这样应用可以使用Router服务,并且应用Component可以访问router指令。

Any feature modules must also import RouterModule so that their components can place router directives into their templates.

任何feature module都必须导入RouterModule,只有这样,feature module包含的Component才能在其template里使用router指令。

If the RouterModule didn’t have forRoot() then each feature module would instantiate a new Router instance, which would break the application as there can only be one Router. By using the forRoot() method, the root application module imports RouterModule.forRoot(…) and gets a Router, and all feature modules import RouterModule.forChild(…) which does not instantiate another Router.

Router实例的单例原则。

How forRoot() works

forRoot() takes a service configuration object and returns a ModuleWithProviders, which is a simple object with the following properties:

  • ngModule: in this example, the GreetingModule class
  • providers: the configured providers

例子:

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 { }

Registering the RouterModule.forRoot() in the AppModule imports array makes the Router service available everywhere in the application.

在AppModule imports数组里注册RouterModule.forRoot的返回结果,确保Router服务在应用的任意位置都能被使用。

The root AppComponent is the application shell. It has a title, a navigation bar with two links, and a router outlet where the router renders components.

The router outlet serves as a placeholder where the routed components are rendered.

router outlet就是一个占位符,用来存放被路由的Component.

Add a wildcard route to intercept invalid URLs and handle them gracefully. A wildcard route has a path consisting of two asterisks. It matches every URL. Thus, the router selects this wildcard route if it can’t match a route earlier in the configuration. A wildcard route can navigate to a custom “404 Not Found” component or redirect to an existing route.

wildcard route就是一个优雅的路由错误处理机制。

{ path: '**', component: PageNotFoundComponent }

如何设置默认路由?

使用redirectTo属性:

const appRoutes: Routes = [{ path: 'crisis-center', component: CrisisListComponent },{ path: 'heroes',        component: HeroListComponent },{ path: '',   redirectTo: '/heroes', pathMatch: 'full' },{ path: '**', component: PageNotFoundComponent }
];

使用Angular CLI创建启用了routing功能的Component:

ng generate module my-module --routing

This tells the CLI to include the @angular/router npm package and create a file named app-routing.module.ts. You can then use routing in any NgModule that you add to the project or app.

const appRoutes: Routes = [{ path: 'crisis-center', component: CrisisListComponent },{ path: 'heroes',        component: HeroListComponent },{ path: '',   redirectTo: '/heroes', pathMatch: 'full' },{ path: '**', component: PageNotFoundComponent }
];@NgModule({imports: [RouterModule.forRoot(appRoutes,{ enableTracing: true } // <-- debugging purposes only)],exports: [RouterModule]
})
export class AppRoutingModule {}

路由时的参数传递

<a [routerLink]="['/hero', hero.id]">

路由url:localhost:4200/hero/15.

The router extracts the route parameter (id:15) from the URL and supplies it to the HeroDetailComponent via the ActivatedRoute service.

Router将路由参数id:15从url里提取出来,通过ActivatedRoute服务传递到路由的目的Component中去。

如何使用ActivatedRoute

constructor(private route: ActivatedRoute,private router: Router,private service: HeroService
) {}

从ActivatedRoute中提取出参数id:

ngOnInit() {this.hero$ = this.route.paramMap.pipe(switchMap((params: ParamMap) =>this.service.getHero(params.get('id'))));
}

When the map changes, paramMap gets the id parameter from the changed parameters.

当参数map发生变化时,上面代码的paramMap从变化的参数里获得id参数。

The switchMap operator does two things. It flattens the Observable that HeroService returns and cancels previous pending requests. If the user re-navigates to this route with a new id while the HeroService is still retrieving the old id, switchMap discards that old request and returns the hero for the new id.

switchMap操作符做的两件事情:将Observable<hero>的返回类型,平整化为Hero,同时cancel之前pending的请求。如果用户重新跳转到这条路由路径,而HeroService仍然在读取前一个id,则old的请求被discard.

为什么要用Observable包裹Param?

In this example, you retrieve the route parameter map from an Observable. That implies that the route parameter map can change during the lifetime of this component.

暗示了存储路由参数的map有可能在该Component生命周期内发生变化。

By default, the router re-uses a component instance when it re-navigates to the same component type without visiting a different component first. The route parameters could change each time.

默认情况下,当我们反复跳转到一个同样的UI时,router重用该UI Component实例。

You wouldn’t want the router to remove the current HeroDetailComponent instance from the DOM only to re-create it for the next id as this would re-render the view. For better UX, the router re-uses the same component instance and updates the parameter.

Router重用Component实例,只是替换parameter值。

Since ngOnInit() is only called once per component instantiation, you can detect when the route parameters change from within the same instance using the observable paramMap property.

ngOnInit在Component整个生命周期里只会触发一次,所以我们可以用Observable包裹过的paramMap属性,来检测参数值的变化。

This application won’t re-use the HeroDetailComponent. The user always returns to the hero list to select another hero to view. There’s no way to navigate from one hero detail to another hero detail without visiting the list component in between. Therefore, the router creates a new HeroDetailComponent instance every time.

如果是list-detail风格的应用,我们无法从一个明细页面跳转到另一个明细页面,中间必须通过list页面的中转。因此,router每次被迫创建新的明细页面Component实例。

When you know for certain that a HeroDetailComponent instance will never be re-used, you can use snapshot.

route.snapshot provides the initial value of the route parameter map. You can access the parameters directly without subscribing or adding observable operators as in the following:

从route.snapshot能获取route参数的初始值。

ngOnInit() {const id = this.route.snapshot.paramMap.get('id');this.hero$ = this.service.getHero(id);
}

snapshot only gets the initial value of the parameter map with this technique. Use the observable paramMap approach if there’s a possibility that the router could re-use the component. This tutorial sample app uses with the observable paramMap.

如果router会重用一个Component,这意味着paramMap在Component生命周期会发生变化,此时要用Observable包裹后的paramMap来检测这种变化。

为什么我们需要Route Guard

  • Perhaps the user is not authorized to navigate to the target component.
  • Maybe the user must login (authenticate) first.
  • Maybe you should fetch some data before you display the target component.
  • You might want to save pending changes before leaving a component.
  • You might ask the user if it’s OK to discard pending changes rather than save them.

通过路由守卫的返回值确定路由是否继续。

  • If it returns true, the navigation process continues.
  • If it returns false, the navigation process stops and the user stays put.
  • If it returns a UrlTree, the current navigation cancels and a new navigation is initiated to the UrlTree returned.

CanActivate: requiring authentication

Applications often restrict access to a feature area based on who the user is. You could permit access only to authenticated users or to users with a specific role. You might block or limit access until the user’s account is activated.
The CanActivate guard is the tool to manage these navigation business rules.

用于实现权限检查。

看一个例子:

实现一个AuthGuard:

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';@Injectable({providedIn: 'root',
})
export class AuthGuard implements CanActivate {canActivate(next: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean {console.log('AuthGuard#canActivate called');return true;}
}

在app module里导入这个AuthGuard,维护到Routes数组元素的canActivate属性里:

import { AuthGuard } from '../auth/auth.guard';const adminRoutes: Routes = [{path: 'admin',component: AdminComponent,canActivate: [AuthGuard],children: [{path: '',children: [{ path: 'crises', component: ManageCrisesComponent },{ path: 'heroes', component: ManageHeroesComponent },{ path: '', component: AdminDashboardComponent }],}]}
];@NgModule({imports: [RouterModule.forChild(adminRoutes)],exports: [RouterModule]
})
export class AdminRoutingModule {}

一个模拟登录的service:

import { Injectable } from '@angular/core';import { Observable, of } from 'rxjs';
import { tap, delay } from 'rxjs/operators';@Injectable({providedIn: 'root',
})
export class AuthService {isLoggedIn = false;// store the URL so we can redirect after logging inredirectUrl: string;login(): Observable<boolean> {return of(true).pipe(delay(1000),tap(val => this.isLoggedIn = true));}logout(): void {this.isLoggedIn = false;}
}

The ActivatedRouteSnapshot contains the future route that will be activated and the RouterStateSnapshot contains the future RouterState of the application, should you pass through the guard check.

If the user is not logged in, you store the attempted URL the user came from using the RouterStateSnapshot.url and tell the router to redirect to a login page—a page you haven’t created yet. Returning a UrlTree tells the Router to cancel the current navigation and schedule a new one to redirect the user.

更多Jerry的原创文章,尽在:“汪子熙”:

Angular里的RouterOutlet指令学习笔记相关推荐

  1. RISC-V 指令学习笔记(基于CH32V103)

    文章目录 RISC-V 指令学习笔记(基于CH32V103) 一.指令结构分类 二.寄存器功能 三.加载存储指令 四.算数运算指令 五.移位指令 六.逻辑操作指令 七.跳转指令 7.1 条件跳转 7. ...

  2. Angular 项目里 angular.json 文件内容的学习笔记

    看一个基于 Angular 的 SAP Spartacus 项目里 angular.json 的例子: version: The configuration-file version. newProj ...

  3. 2020国庆节 Angular structual 指令学习笔记(<ng-template>) 包含语法糖解糖过程

    Structural directives are responsible for HTML layout. They shape or reshape the DOM's structure, ty ...

  4. arm ida 伪代码 安卓 符号表_使用IDA动态调试及ARM指令学习笔记

    本文介绍如何用IDA进行动态调试及部分ARM指令的学习. 环境:已root的安卓手机一部,IDA pro 6.8,win7系统. 下载样本app,并已确认可调试(debuggable = true), ...

  5. 使用mkiso向服务器传文件,Linux mkisofs 创建光盘镜像文件(Linux指令学习笔记)

    mkisofs命令 创建光盘文件的系统的命令是mkisofs.光盘系统有多种格式,利用Linux系统提供的光盘文件系统创建 命令mkisofs,可以创建多种iso9660文件系统. 我们一般不用mki ...

  6. Angular 服务端渲染(SSR) 学习笔记

    文章目录 1 服务器端渲染 (SSR) 2 SSR的利弊 2.1 SSR的优势 2.2 SSR的局限 3 Angular Universal 3.1 Node.js Express web serve ...

  7. Linux实操篇——实用指令学习笔记(详解)

    9.3帮助指令 9.3.1介绍 当我们对某个指令不熟悉时,我们可以使用Linux提供的帮助指令来了解这个指令的使用方法. 9.3.2man 获得帮助信息 基本语法 man[命令或配置文件](功能描述: ...

  8. ESP8266及AT指令学习笔记

    一.ESP8266实物图(01s) ESP8266 尺寸为5x5 mm,ESP8266 模组需要的外围器件有:10个电阻电容电感.1个无源晶振.1个flash.工作温度范围:-40~125℃.ESP8 ...

  9. ARM汇编指令学习笔记(一)

    (一)数据常量定义汇编指令EQU EQU用于为程序中的常量.标号等定义一个有效的字符名称,类似于C语言中的#define,当表达式为32位常量时,可指定表达式的数据类型,CODE16,CODE32,D ...

最新文章

  1. java多线程中的join方法详解
  2. python类继承中构造方法_第8.3节 Python类的__init__方法深入剖析:构造方法与继承详解...
  3. python3 安装opencv_树莓派安装Python3的OpenCV
  4. 编译错误:GL/glew.h, GL/glut.h, EGL/egl.h没有那个文件或目录
  5. 联想X1电脑键盘无法输入,外接键盘也无法输入
  6. 复旦计算机系统基础课件,复旦大学软件工程考研(MSE)计算机系统基础复习资料.ppt...
  7. 使用健康档案数据计算OLT的用户光衰不合格率
  8. 怎样制作文章视频gif插图?视频gif格式图片如何在线制作?
  9. SIM800C AT指令编程
  10. Leetcode #1 Two Sum
  11. 计算机基础考试试题(扩招考试),大学计算机科学基础探析论文
  12. ROS键盘控制机器人
  13. matlab maps 指北针和比例尺,第5步:制作地图(指北针、比例尺、图例).doc
  14. 判断bigdecimal类型是正负数还是0+bigdecimal正负数转换
  15. 苹果系统中英文输入法切换_Mac系统,如何优雅切换中英文?
  16. 如何通过组策略控制远程主机空闲时间自动断开并注销
  17. html点击出现对勾,html , 对勾,警告,错误 三种情况
  18. Linux忘记密码的解决方法
  19. 2020-3-17课堂笔记
  20. filebeat 收集json格式_Filebeat 采集日志实践经验记录

热门文章

  1. 理解JWT(JSON Web Token)认证及python实践
  2. JavaScript强化教程 —— JavaScript 总结
  3. 随便写写2014创业记(二)
  4. 华为 命令 so easy
  5. PHPCMS后台框架实现思路
  6. framework7 1.3.5 路由跳转后DOM失效问题
  7. PHP base64
  8. 如何升级cordova插件
  9. 在MAC中配置Tomcat+Nginx代理
  10. 阿里大数据分析与应用(part5)--QuickBI