官网: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.
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事件。应用程序可以监听这个事件。
(activate)='onActivate($event)'
(deactivate)='onDeactivate($event)'>
路由配置对象: 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
在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 }
1
如何设置默认路由?
使用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 {}
路由时的参数传递
Router将路由参数id:15从url里提取出来,通过ActivatedRoute服务传递到路由的目的Component中去。
private route: ActivatedRoute,
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参数。
暗示了存储路由参数的map有可能在该Component生命周期内发生变化。
默认情况下,当我们反复跳转到一个同样的UI时,router重用该UI Component实例。
Router重用Component实例,只是替换parameter值。
ngOnInit在Component整个生命周期里只会触发一次,所以我们可以用Observable包裹过的paramMap属性,来检测参数值的变化。
如果是list-detail风格的应用,我们无法从一个明细页面跳转到另一个明细页面,中间必须通过list页面的中转。因此,router每次被迫创建新的明细页面Component实例。
从route.snapshot能获取route参数的初始值。
const id = this.route.snapshot.paramMap.get('id');
this.hero$ = this.service.getHero(id);
如果router会重用一个Component,这意味着paramMap在Component生命周期会发生变化,此时要用Observable包裹后的paramMap来检测这种变化。
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.
CanActivate: requiring authentication
The CanActivate guard is the tool to manage these navigation business rules.
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
export class AuthGuard implements CanActivate {
state: RouterStateSnapshot): boolean {
console.log('AuthGuard#canActivate called');
在app module里导入这个AuthGuard,维护到Routes数组元素的canActivate属性里:
import { AuthGuard } from '../auth/auth.guard';
{ path: 'crises', component: ManageCrisesComponent },
{ path: 'heroes', component: ManageHeroesComponent },
{ path: '', component: AdminDashboardComponent }
RouterModule.forChild(adminRoutes)
export class AdminRoutingModule {}
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { tap, delay } from 'rxjs/operators';
// store the URL so we can redirect after logging in
tap(val => this.isLoggedIn = true)