日月长存 發表於 2020-12-4 17:33:00

Angular(4)路由

<h1 id="1-最基本的路由">1. 最基本的路由</h1>
<h2 id="11-api">1.1 API:</h2>
<ul>
<li>Router</li>
<li>ActivatedRoute</li>
</ul>
<p>路由的基本使用</p>
<table>
<thead>
<tr>
<th style="text-align: left">名称</th>
<th style="text-align: left">简介</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left">Routes</td>
<td style="text-align: left">路由的配置,保存着哪一个URL对应展示哪一个组件和在哪一个RouterOutler展示</td>
</tr>
<tr>
<td style="text-align: left">RouterOutler</td>
<td style="text-align: left">在HTML中标记路由内容呈现的占位符指令</td>
</tr>
<tr>
<td style="text-align: left">Router</td>
<td style="text-align: left">运行时执行的路由对象,可以通过navigate()和navigateByUrl()方法来导航到指定路由</td>
</tr>
<tr>
<td style="text-align: left">RouterLink</td>
<td style="text-align: left">在HTML中声明导航的指令</td>
</tr>
<tr>
<td style="text-align: left">ActivatedRoute</td>
<td style="text-align: left">当前激活的路由对象,保存着当前路由信息,路由地址,路由参数</td>
</tr>
</tbody>
</table>
<h2 id="12-将路由添加到-appmodules">1.2 将路由添加到 app.modules</h2>
<p>app.module.ts</p>
<pre><code class="language-js">import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { HeroListComponent } from './router-study/heroes/hero-list/hero-list.component';
import { RouterModule, Routes } from '@angular/router';
import { CrisisListComponent } from './router-study/crisis-center/crisis-list/crisis-list.component';
import { NotFoundComponent } from './router-study/not-found/not-found.component';

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

@NgModule({
declarations: [
    AppComponent,
    HeroListComponent,
    CrisisListComponent,
    NotFoundComponent,
],
imports: [
    BrowserModule,
    RouterModule.forRoot(routes)
],
providers: [],
bootstrap:
})
export class AppModule { }
</code></pre>
<p>app.components.html</p>
<pre><code class="language-html">&lt;div class="app"&gt;
    &lt;h2&gt;Router Study&lt;/h2&gt;
    &lt;nav&gt;
      &lt;a routerLink = "/crisis-center" routerLinkActive="act-link"&gt;crisis center&lt;/a&gt;||
      &lt;a routerLink = "/heroes" routerLinkActive="act-link"&gt;heroes&lt;/a&gt;
    &lt;/nav&gt;
    &lt;router-outlet&gt;&lt;/router-outlet&gt;
&lt;/div&gt;
</code></pre>
<h2 id="知识点总结">知识点总结</h2>
<h3 id="创建路由">创建路由</h3>
<pre><code class="language-js">ng new routing-app --routing
</code></pre>
<h3 id="路由配置">路由配置</h3>
<blockquote>
<p>注意:path里面不要加 \ 线</p>
</blockquote>
<pre><code class="language-js">import { RouterModule, Routes } from '@angular/router';

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

imports: [
    RouterModule.forRoot(routes)
],
</code></pre>
<h3 id="路由出口">路由出口</h3>
<pre><code class="language-js">&lt;router-outlet&gt;&lt;/router-outlet&gt;
</code></pre>
<h3 id="路由跳转">路由跳转</h3>
<pre><code class="language-js">&lt;a routerLink = "/heroes"&gt;heroes&lt;/a&gt;
</code></pre>
<h3 id="路由高亮">路由高亮</h3>
<pre><code class="language-html">&lt;a routerLink = "/crisis-center" routerLinkActive="act-link"&gt;crisis center&lt;/a&gt;
&lt;a routerLink = "/heroes" routerLinkActive="act-link"&gt;heroes&lt;/a&gt;
//==================================================================
.act-link{
        color:red;
}
</code></pre>
<h3 id="路由404">路由404</h3>
<blockquote>
<p>注意: 配置里面通配符代表没有的都往这里,注意这里不能写在前面,不然angualr的路由会优先匹配这里</p>
</blockquote>
<pre><code class="language-js"> { path: '**', component:NotFoundComponent },
// { path: '**', redirectTo: '/heroes' },
</code></pre>
<h3 id="路由为空-重定向">路由为空-重定向</h3>
<pre><code class="language-js">{ path: '', redirectTo: '/heroes' ,pathMatch: 'full'},
// { path: '', component:HeroListComponent },
</code></pre>
<h1 id="路由模块">路由模块</h1>
<h2 id="创建app路由模块">创建app路由模块</h2>
<ul>
<li>app.routing.module.ts</li>
</ul>
<pre><code class="language-js">ng new routing-app --routing
</code></pre>
<h3 id="添加-approutingmodule">添加 AppRoutingModule</h3>
<p>在 Angular 中,最好在一个独立的顶层模块中加载和配置路由器,它专注于路由功能,然后由根模块 <code>AppModule</code> 导入它。</p>
<p>按照惯例,这个模块类的名字叫做 AppRoutingModule,并且位于 <code>src/app</code> 下的 app-routing.module.ts 文件中。</p>
<p>使用 CLI 生成它。</p>
<pre><code>ng generate module app-routing --flat --module=app
</code></pre>
<blockquote>
<p>--flat 把这个文件放进了 <code>src/app</code> 中,而不是单独的目录中。</p>
<p>--module=app告诉 CLI 把它注册到 AppModule 的 imports 数组中。</p>
</blockquote>
<p>app.module.ts</p>
<pre><code class="language-js">import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { HeroListComponent } from './router-study/heroes/hero-list/hero-list.component';
import { CrisisListComponent } from './router-study/crisis-center/crisis-list/crisis-list.component';
import { NotFoundComponent } from './router-study/not-found/not-found.component';

import { AppRoutingModule } from './app-routing.module';
import { HeroesModule } from './router-study/heroes/heroes.module';
import { CrisisCenterModule } from './router-study/crisis-center/crisis-center.module';


@NgModule({
declarations: [
    AppComponent,
    HeroListComponent,
    CrisisListComponent,
    NotFoundComponent,
],
imports: [
    BrowserModule,
    CrisisCenterModule,
    HeroesModule,
    AppRoutingModule, //这个模块必须放在最后,否则会被通配符组件/模块 拦截
],
providers: [],
bootstrap:
})
export class AppModule { }

</code></pre>
<p>app.routing.module.ts</p>
<pre><code class="language-js">import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { HeroListComponent } from './router-study/heroes/hero-list/hero-list.component';
import { CrisisListComponent } from './router-study/crisis-center/crisis-list/crisis-list.component';
import { NotFoundComponent } from './router-study/not-found/not-found.component';

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

@NgModule({
declarations: [], //这里不用声明组件
imports: [
    RouterModule.forRoot(routes),
],
exports: [ RouterModule ]//记得导出路由模块
})
export class AppRoutingModule { }

</code></pre>
<p>app.module.ts</p>
<pre><code class="language-js">import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { HeroListComponent } from './router-study/heroes/hero-list/hero-list.component';
import { CrisisListComponent } from './router-study/crisis-center/crisis-list/crisis-list.component';
import { NotFoundComponent } from './router-study/not-found/not-found.component';

import { AppRoutingModule } from './app-routing.module';

@NgModule({
declarations: [
    AppComponent,
    HeroListComponent,
    CrisisListComponent,
    NotFoundComponent,
],
imports: [
    BrowserModule,
    AppRoutingModule
],
providers: [],
bootstrap:
})
export class AppModule { }

</code></pre>
<h2 id="app-路由模块再次拆分">app 路由模块再次拆分</h2>
<p>app.routing.module.ts</p>
<pre><code class="language-js">import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { NotFoundComponent } from './router-study/not-found/not-found.component';

const routes: Routes = [
{ path: '', redirectTo: '/heroes' ,pathMatch: 'full'},
{ path: '**', component:NotFoundComponent },
];

@NgModule({
imports: [
   RouterModule.forRoot(routes),
],
exports: [ RouterModule ]
})
export class AppRoutingModule { }

</code></pre>
<p>crisis-center-routing.module.ts</p>
<pre><code class="language-js">import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { CrisisListComponent } from './crisis-list/crisis-list.component';

const routes: Routes = [
{ path: 'crisis-center', component: CrisisListComponent },
];

@NgModule({
imports: ,
exports:
})
export class CrisisCenterRoutingModule { }

</code></pre>
<p>heros-routing.module.ts</p>
<pre><code class="language-js">import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HeroListComponent } from './hero-list/hero-list.component';

const routes: Routes = [
{ path: 'heroes', component:HeroListComponent },
];

@NgModule({
imports: ,
exports:
})
export class HeroesRoutingModule { }
</code></pre>
<blockquote>
<p>补充:完成后需要把路由模块导入相应的管理模块,然后将管理模块导入app.module.ts根模块,形成树结构进行统一管理</p>
</blockquote>
<h1 id="路由导航">路由导航</h1>
<p>API :   https://angular.cn/api/router/Router</p>
<h2 id="声明式路由导航">声明式路由导航</h2>
<ul>
<li>routerLink</li>
</ul>
<pre><code class="language-js">&lt;a routerLink = "/crisis-center" routerLinkActive="act-link"&gt;crisis center&lt;/a&gt;||
&lt;a routerLink = "/heroes" routerLinkActive="act-link"&gt;heroes&lt;/a&gt;

//&lt;a ="['/crisis-center']" routerLinkActive="act-link" &gt;crisis center&lt;/a&gt;
//&lt;a ="['/heroes']" routerLinkActive="act-link" &gt;heroes&lt;/a&gt;
</code></pre>
<h2 id="编程式路由导航">编程式路由导航</h2>
<ul>
<li>navigateByUrl</li>
<li>navigate</li>
</ul>
<pre><code class="language-js"> &lt;a (click)="toCrisisCenter()" routerLinkActive="act-link"&gt;crisis center&lt;/a&gt;||
&lt;a (click)="toHeroes()" routerLinkActive="act-link"&gt;heroes&lt;/a&gt;
</code></pre>
<pre><code class="language-js">export class AppComponent {
constructor(private router:Router){}

toCrisisCenter(){
    this.router.navigateByUrl('/crisis-center');
    // this.router.navigate( ['/crisis-center']);
}
toHeroes(){
    this.router.navigateByUrl('/heroes');
    // this.router.navigate( ['/heroes']);
      
}
}
</code></pre>
<h2 id="onsameurlnavigation">onSameUrlNavigation</h2>
<ul>
<li>onSameUrlNavigation: 'reload' | 'ignore'</li>
</ul>
<p>定义当路由器收到一个导航到当前 URL 的请求时应该怎么做。可取下列值之一:</p>
<p><code>'ignore'</code>:路由器会忽略此请求。</p>
<p><code>'reload'</code>:路由器会重新加载当前 URL。用来实现"刷新"功能。</p>
<p>app.routeing.module.ts</p>
<pre><code class="language-js">//imports: ,

imports: [RouterModule.forRoot(routes,{
        onSameUrlNavigation:'reload',
    //enableTracing:true用来测试,监测路由变化
})],
</code></pre>
<h1 id="路由参数">路由参数</h1>
<ul>
<li>API—https://angular.cn/api/router/ActivatedRoute</li>
</ul>
<h2 id="params">params</h2>
<h3 id="传递产数到地址栏并跳转">传递产数到地址栏并跳转</h3>
<ul>
<li>当有 id 导航到详情页</li>
</ul>
<pre><code class="language-js">const routes: Routes = [
{ path: 'heroes', component:HeroListComponent },
{ path: 'hero/:id', component:HeroDetailComponent },
];
</code></pre>
<ul>
<li>获取当前点击的 id ,并提交到地址栏,经由上面的路由跳转到详情页</li>
</ul>
<pre><code class="language-js">constructor(private router:Router){}

onSelect(id:number){
    this.selectedId = id;
    //this.router.navigateByUrl('/hero/' + id);或者
    this.router.navigate( ['/heroes', id]);
    //this.router.navigate( ['/heroes', id, 'aaa']);
}
</code></pre>
<pre><code class="language-ts">="['/hero', hero.id]"&gt;{{ hero.name }}&lt;/li&gt;
</code></pre>
<h3 id="提取地址栏-id">提取地址栏 id</h3>
<ul>
<li>提取当前地址栏 id ,然后根据id进入当前id的英雄详情</li>
</ul>
<p>hero-detail.component.ts</p>
<pre><code class="language-js">import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { Hero } from '../hero';
import { HeroService } from '../hero.service';
@Component({
selector: 'app-hero-detail',
templateUrl: './hero-detail.component.html',
styleUrls: ['./hero-detail.component.scss']
})
export class HeroDetailComponent implements OnInit {
constructor(
   private router: Router,
   private route: ActivatedRoute,
   private heroService: HeroService
   ) { }
// ngOnInit(): void {
//   this.route.paramMap.subscribe(params =&gt;{
//   console.log("params",params.get('id'));
//   this.heroService.getHero(params.get('id')).subscribe(hero=&gt;{
//       console.log('hero',hero);
//   })
//   })
// }
hero$: Observable&lt;Hero&gt;;
ngOnInit(): void {   //返回 id对应的英雄数据
    this.hero$ = this.route.paramMap.pipe(switchMap(params =&gt; {
      return this.heroService.getHero(params.get('id'));
   })) ;      
}
back(id:number){
   this.router.navigate(['/heroes',{id}])
}
}
</code></pre>
<ul>
<li>显示英雄详情</li>
</ul>
<pre><code class="language-js">&lt;div *ngIf="hero$ | async as hero"&gt;
&lt;h2&gt;英雄详情&lt;/h2&gt;
&lt;h3&gt;"{{ hero.name }}"&lt;/h3&gt;
&lt;div&gt;
    &lt;label&gt;Id: &lt;/label&gt;{{ hero.id }}&lt;/div&gt;
&lt;div&gt;
    &lt;label&gt;Name: &lt;/label&gt;
    &lt;input [(ngModel)]="hero.name" placeholder="name"/&gt;
&lt;/div&gt;
&lt;p&gt;
      
    //返回
    //&lt;button (click)="back(hero.id)" class="btn btn-secondary"&gt;Back to Heroes&lt;/button&gt;
    &lt;button ="['/heroes', { id: hero.id }]" class="btn btn-secondary"&gt;Back to Heroes&lt;/button&gt;
&lt;/p&gt;
&lt;/div&gt;
</code></pre>
<h3 id="过滤出-id-对应的英雄数据">过滤出 id 对应的英雄数据</h3>
<ul>
<li>服务里有两个方法</li>
<li>getHeroes( ) 用来获取英雄列表数据</li>
<li>getHero( ) 用来从英雄列表里搜索当前 id,并返回为当前 id 的英雄数据</li>
</ul>
<p>heroes/hero.service.ts</p>
<pre><code class="language-ts">import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { Hero } from './hero';
import { HEROES } from './mock-heroes';
import {map} from 'rxjs/operators';

@Injectable({
providedIn: 'root',
})
export class HeroService {
constructor() { }

getHeroes(): Observable&lt;Hero[]&gt; {
    return of(HEROES);
}

getHero(id: number | string) {
    return this.getHeroes().pipe(
      map((heroes: Hero[]) =&gt; heroes.find(hero =&gt; hero.id === +id))
    );
}
}
</code></pre>
<p>hero-list/hero-list.components.ts</p>
<pre><code class="language-js">@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
styles: [
    `
      .list-group {width: 280px;cursor: pointer;}
    `
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HeroListComponent implements OnInit {
heroes$: Observable&lt;Hero[]&gt;;
selectedId: number;
constructor(private heroServe: HeroService, private router: Router, private route: ActivatedRoute) { }

/*ngOnInit(): void {
    // this.heroes$ = this.heroServe.getHeroes();
    this.heroes$ = this.route.paramMap.pipe(
      switchMap(params =&gt; {
      console.log('params list', params);
      this.selectedId = +params.get('id');
      return this.heroServe.getHeroes();
      })
    );
}*/

ngOnInit(): void {
    this.selectedId = +this.route.snapshot.paramMap.gest('id');
    this.heroes$ = this.heroServe.getHeroes();
    // this.getQueryName();
}

private getQueryName() {
    console.log(this.route.snapshot.queryParamMap.get('name'));
    /* this.route.queryParamMap.subscribe(res =&gt; {
       console.log(res.get('name'));
   });*/
}

onSelect(id: number) {
    // this.selectedId = id;
    // this.router.navigateByUrl('/hero/' + id);
    this.router.navigate(['/hero', id]);
}
}

</code></pre>
<h3 id="点击返回后依然显示高亮">点击返回后依然显示高亮</h3>
<ul>
<li>数据显示</li>
<li>再次传参到 地址栏</li>
</ul>
<pre><code class="language-js">&lt;div *ngIf="hero$ | async as hero"&gt;
    &lt;h2&gt;英雄详情&lt;/h2&gt;
    &lt;h3&gt;"{{ hero.name }}"&lt;/h3&gt;
    &lt;div&gt;
      &lt;label&gt;Id: &lt;/label&gt;{{ hero.id }}&lt;/div&gt;
    &lt;div&gt;
      &lt;label&gt;Name: &lt;/label&gt;
      &lt;input [(ngModel)]="hero.name" placeholder="name"/&gt;
    &lt;/div&gt;
    &lt;p&gt;
      &lt;button (click)="back(hero.id)" class="btn btn-secondary"&gt;
          Back to Heroes
      &lt;/button&gt;



       // back(id:number){
       //       this.router.navigate(['/heroes',{id}]){id:id}的简写
           // }
      &lt;button ="['/heroes', { id: hero.id }]" class="btn btn-secondary"&gt;
          Back to Heroes
      &lt;/button&gt;
    &lt;/p&gt;
&lt;/div&gt;
</code></pre>
<ul>
<li>再次拿到地址栏 id</li>
<li>根据 id 显示对应的高亮</li>
</ul>
<pre><code class="language-js">export class HeroListComponent implements OnInit {
heroes$: Observable&lt;Hero[]&gt;;
selectedId:number;
constructor(private route: ActivatedRoute, private heroService: HeroService, private router:Router) { }

ngOnInit(): void {
    // this.heroes$ = this.heroService.getHeroes();
    this.heroes$ = this.route.paramMap.pipe(
      switchMap(params =&gt; {
      console.log('params',params)
      this.selectedId = +params.get('id');
      return this.heroService.getHeroes()
      })
    );
}
onSelect(id:number){
    // this.selectedId = id;
    this.router.navigateByUrl('/hero/' + id);
}
}
</code></pre>
<h2 id="query后参数">query(?后参数)</h2>
<h3 id="parammap">paramMap</h3>
<pre><code class="language-js">//https://www.xxxx?name=jack

//this.route.queryParamMap.subscribe(res =&gt;{
//        console.log(res.get('name'))
//})
this.route.snapshot.queryParamMap.get('name')
</code></pre>
<h3 id="queryparammap">queryParamMap</h3>
<pre><code class="language-js">ngOnInit() {
this.selectedId = +this.route.snapshot.paramMap.get('id');
// +转数字类型
this.heroes$ = this.heroService.getHeroes();   
// this.getQueryName()
}
//getQueryName(){
//    this.route.queryParamMap.subscribe(res=&gt;{
//      console.log('res',res)
//      console.log( res.get('name'))       
//    })
等价于
//console.log(this.route.snapshot.queryParamMap.get('name'))

//}
</code></pre>
<h2 id="snapshot">snapshot</h2>
<pre><code class="language-js">ngOnInit(): void{
        this.selectedId= +this.route.snapshot.paramMap.get('id');
        this.heroes$ = this.heroServe.getHeroes();
}
</code></pre>
<h1 id="嵌套路由和相对导航">嵌套路由和相对导航</h1>
<p>嵌套路由</p>
<pre><code class="language-js">const crisisCenterRoutes: Routes = [
{
    path: 'crisis-center',
    component: CrisisCenterComponent,
    children: [
      {
      path: '',
      component: CrisisListComponent,
      children: [
          {
            path: ':id',
            component: CrisisDetailComponent
          },
          {
            path: '',
            component: CrisisCenterHomeComponent
          }
      ]
      }
    ]
}
];
</code></pre>
<p>s</p>
<pre><code class="language-js">&lt;div class="crisis-certer"&gt;
    &lt;h2&gt;危机中心&lt;/h2&gt;
    &lt;router-outlet&gt;&lt;/router-outlet&gt;
        //记得写插槽
&lt;/div&gt;
</code></pre>
<h2 id="相对导航">相对导航</h2>
<pre><code class="language-js">//导航到上一级
&lt;li&gt;&lt;a routerLink="../"&gt;Relative Route to second component&lt;/a&gt;&lt;/li&gt;
//
&lt;li&gt;&lt;a routerLink="../second-component"&gt;Relative Route to second component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a routerLink="../second-component"&gt;Relative Route to second component&lt;/a&gt;&lt;/li&gt;


goToItems() {
this.router.navigate(['items'], { relativeTo: this.route });
}
</code></pre>
<h1 id="多重路由具名路由">多重路由(具名路由)</h1>
<pre><code class="language-js">//&lt;div [@routeAnimation]="getAnimationData(routerOutlet)"&gt;
//&lt;router-outlet #routerOutlet="outlet"&gt;&lt;/router-outlet&gt;
//&lt;/div&gt;
&lt;router-outlet name="popup"&gt;&lt;/router-outlet&gt;
</code></pre>
<p>outlet</p>
<pre><code class="language-js">{
path: 'compose',
component: ComposeMessageComponent,
outlet: 'popup'
},
</code></pre>
<p>点击跳到 ComposeMessageComponent 组件</p>
<pre><code class="language-js">&lt;a ="[{ outlets: { popup: ['compose'] } }]"&gt;Contact&lt;/a&gt;
</code></pre>
<p>导航到<em>危机中心</em>并点击“Contact”,你将会在浏览器的地址栏看到如下 URL:</p>
<pre><code>http://.../crisis-center(popup:compose)
</code></pre>
<p>清除第二路由</p>
<pre><code class="language-js">closePopup() {
// Providing a `null` value to the named outlet
// clears the contents of the named outlet
this.router.navigate([{ outlets: { popup: null }}]);
}
</code></pre>
<h1 id="路由守卫">路由守卫</h1>
<p>路由器可以支持多种守卫接口:</p>
<ul>
<li>用<code>CanActivate</code>来处理导航到某路由的情况。</li>
<li>用<code>CanActivateChild</code>来处理导航到某子路由的情况。</li>
<li>用<code>CanDeactivate</code>来处理从当前路由离开的情况.</li>
<li>用<code>Resolve</code>在路由激活<strong>之前</strong>获取路由数据。</li>
<li>用<code>CanLoad</code>来处理<strong>异步</strong>导航到某特性模块的情况。</li>
</ul>
<h2 id="canactivate">CanActivate</h2>
<h3 id="最简单的canactivate">最简单的CanActivate</h3>
<ul>
<li>只让登录用户进入产品信息路由。</li>
</ul>
<p>新建guard目录。目录下新建login.guard.ts。</p>
<pre><code class="language-js">//LoginGuard类实现CanActivate接口,返回true或false,Angular根据返回值判断请求通过或不通过。

import { CanActivate } from "@angular/router";

export class LoginGuard implements CanActivate{
    canActivate(){
      let loggedIn :boolean= Math.random()&lt;0.5;
      if(!loggedIn){
            console.log("用户未登录");
      }
      return loggedIn;
    }
}
</code></pre>
<p>配置product路由。先把LoginGuard加入providers,在指定路由守卫。</p>
<p>canActivate可以指定多个守卫,值是一个数组。</p>
<pre><code class="language-js">const routes: Routes = [
{ path: '', redirectTo : 'home',pathMatch:'full' },
{ path: 'chat', component: ChatComponent, outlet: "aux"},//辅助路由
{ path: 'home', component: HomeComponent },
{ path: 'product/:id', component: ProductComponent, children:[
    { path: '', component : ProductDescComponent },
      
    { path: 'seller/:id', component : SellerInfoComponent }
] ,canActivate: },
   
{ path: '**', component: Code404Component }
];
</code></pre>
<h3 id="登录功能模拟">登录功能模拟</h3>
<pre><code class="language-js">&lt;h1 class="title"&gt;Angular Router&lt;/h1&gt;
&lt;nav&gt;
&lt;a routerLink="/crisis-center" routerLinkActive="active"&gt;Crisis Center&lt;/a&gt;
&lt;a routerLink="/heroes" routerLinkActive="active"&gt;Heroes&lt;/a&gt;
//
&lt;a routerLink="/admin" routerLinkActive="active"&gt;Admin&lt;/a&gt;
&lt;a ="[{ outlets: { popup: ['compose'] } }]"&gt;Contact&lt;/a&gt;
&lt;/nav&gt;
&lt;div [@routeAnimation]="getAnimationData(routerOutlet)"&gt;
&lt;router-outlet #routerOutlet="outlet"&gt;&lt;/router-outlet&gt;
&lt;/div&gt;js
&lt;router-outlet name="popup"&gt;&lt;/router-outlet&gt;
</code></pre>
<p>src/app/admin/admin-routing.module.ts</p>
<pre><code class="language-js">import { AuthGuard } from '../auth/auth.guard';

const adminRoutes: Routes = [
{
    path: 'admin',
    component: AdminComponent,
    canActivate: ,//路由导航到admin时触发canActivate验证
      
    children: [
      {
      path: '',
      children: [
          { path: 'crises', component: ManageCrisesComponent },
          { path: 'heroes', component: ManageHeroesComponent },
          { path: '', component: AdminDashboardComponent }
      ],
      }
    ]
}
];

@NgModule({
imports: [
    RouterModule.forChild(adminRoutes)
],
exports: [
    RouterModule
]
})
export class AdminRoutingModule {}
</code></pre>
<p>添加验证</p>
<p>src/app/auth/auth.service.ts (excerpt)</p>
<pre><code class="language-js">import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { tap, delay } from 'rxjs/operators';

@Injectable({
providedIn: 'root',
})
export class AuthService {
isLoggedIn = false;
//存储URL以便我们可以在登录后重定向
redirectUrl: string;
//点击登录,将isLogedIn,一秒后改为true
login(): Observable&lt;boolean&gt; {
    return of(true).pipe(
      delay(1000),
      tap(val =&gt; this.isLoggedIn = true)
    );
}
//点击退出,将isLoggedIn改为false
logout(): void {
    this.isLoggedIn = false;
}
}
</code></pre>
<p>src/app/auth/auth.guard.ts (v2)</p>
<ul>
<li>这个 <code>ActivatedRouteSnapshot</code> 包含了<em>即将</em>被激活的路由,</li>
<li>而 <code>RouterStateSnapshot</code> 包含了该应用<em>即将</em>到达的状态。 你应该通过守卫进行检查。</li>
<li>如果用户还没有登录,你就会用RouterStateSnapshot.url 保存用户来自的 URL 并让路由器跳转到登录页(你尚未创建该页)。 这间接导致路由器自动中止了这次导航,checkLogin()返回false并不是必须的,但这样可以更清楚的表达意图。</li>
</ul>
<pre><code class="language-js">import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';

import { AuthService } from './auth.service';

@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}

canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): true | UrlTree {
    let url: string = state.url;//admin,被canActivate阻止进入的路由
    return this.checkLogin(url);//如果isLoggedIn为true,直接进入,反之跳到login登录页
}
//返回true,或者一个地址(UrlTree)
checkLogin(url: string): true | UrlTree {
    if (this.authService.isLoggedIn) { return true; }
    this.authService.redirectUrl = url; //登录成功后重定向到admin
    return this.router.parseUrl('/login');
}
}
</code></pre>
<p>src/app/auth/login/login.html</p>
<pre><code class="language-html">&lt;h2&gt;LOGIN&lt;/h2&gt;
&lt;p&gt;{{message}}&lt;/p&gt;
&lt;p&gt;
&lt;button (click)="login()"*ngIf="!authService.isLoggedIn"&gt;Login&lt;/button&gt;
&lt;button (click)="logout()" *ngIf="authService.isLoggedIn"&gt;Logout&lt;/button&gt;
&lt;/p&gt;
</code></pre>
<p>src/app/auth/login/login.ts</p>
<pre><code class="language-js">import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import {AuthService} from '../auth.service';
import {Router} from '@angular/router';

@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styles: [
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class LoginComponent {
message: string;

constructor(public authService: AuthService, public router: Router) {
    this.setMessage();
}

setMessage() {
    this.message = 'Logged ' + (this.authService.isLoggedIn ? 'in' : 'out');
}

login() {
    this.message = 'Trying to log in ...';

    this.authService.login().subscribe(() =&gt; {
      this.setMessage();
      if (this.authService.isLoggedIn) {
      const redirectUrl = this.authService.redirectUrl;

      // Redirect the user
      this.router.navigate();
      }
    });
}

logout() {
    this.authService.logout();
    this.setMessage();
}
}

</code></pre>
<h2 id="canactivatechild">CanActivateChild</h2>
<pre><code class="language-js">import { Injectable } from '@angular/core';
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree, CanActivateChild} from '@angular/router';
import {AuthService} from './auth.service';

@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private authService: AuthService, private router: Router) {}

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): true | UrlTree {
    const url = state.url;
    console.log('canActivate', url);
    return this.checkLogin(url);
}

canActivateChild(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): true | UrlTree {
    console.log('canActivateChild');
    return this.canActivate(route, state);
}

checkLogin(url: string): true | UrlTree {
    if (this.authService.isLoggedIn) { return true; }

    // Store the attempted URL for redirecting
    this.authService.redirectUrl = url;
    // Redirect to the login page
    return this.router.parseUrl('/login');
}
}

</code></pre>
<p>这个 <code>AuthGuard</code> 添加到“无组件的”管理路由,来同时保护它的所有子路由,而不是为每个路由单独添加这个 <code>AuthGuard</code>。</p>
<p>admin/admin-routing.modul.ts</p>
<pre><code class="language-js">const routes: Routes = [
{
    path: 'admin',
    component: AdminComponent,
    canActivate: ,
    children: [
      {
      path: '',
      canActivateChild: ,
      children: [
          { path: 'crises', component: ManageCrisesComponent },
          { path: 'heroes', component: ManageHeroesComponent },
          { path: '', component: AdminDashboardComponent }
      ]
      }
    ]
}
];

@NgModule({
imports: ,
exports:
})
export class AdminRoutingModule { }

</code></pre>
<h2 id="candeactivate">CanDeactivate</h2>
<p>crisis-center-routing.module.ts</p>
<pre><code class="language-js">const routes: Routes = [
{
    path: 'crisis-center',
    component: CrisisCenterComponent,
    children: [
      {
      path: 'list',
      component: CrisisListComponent,
      children: [
          {
            path: ':id',
            component: CrisisDetailComponent,
            canDeactivate: //从详情页离开时,激活判断
          },
          {
            path: '',
            component: CrisisCenterHomeComponent
          }
      ]
      },
      {
      path: '',
      redirectTo: 'list',
      pathMatch: 'full'
      }
    ]
},
];

@NgModule({
imports: ,
exports:
})
export class CrisisCenterRoutingModule { }

</code></pre>
<p>can-deactivate.guard.ts</p>
<pre><code class="language-js">import { Injectable } from '@angular/core';
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, CanDeactivate} from '@angular/router';
import {CrisisDetailComponent} from './crisis-detail/crisis-detail.component';
@Injectable({
providedIn: 'root'
})
export class CanDeactivateGuard implements CanDeactivate&lt;CrisisDetailComponent&gt; {
canDeactivate(
    component: CrisisDetailComponent,
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
    ) {
    console.log('url', state.url);
    return component?.canDeactivate();
    //守卫不需要知道哪个组件有 deactivate 方法,
    //它可以检测 CrisisDetailComponent 组件有没有 canDeactivate() 方法并调用它。
    //守卫在不知道任何组件 deactivate 方法细节的情况下,就能让这个守卫重复使用。
}
}

</code></pre>
<p>crisis-detail.component.html</p>
<pre><code class="language-js">&lt;div *ngIf="crisis"&gt;
&lt;h5&gt;英雄详情&lt;/h5&gt;
&lt;h2&gt;{{crisis.name | uppercase}} Details&lt;/h2&gt;
&lt;div&gt;&lt;span&gt;id: &lt;/span&gt;{{crisis.id}}&lt;/div&gt;
&lt;div&gt;
    &lt;label&gt;name:
      &lt;input [(ngModel)]="crisis.name" placeholder="name" /&gt;
    &lt;/label&gt;
&lt;/div&gt;
&lt;div class="btns"&gt;
    &lt;button class="btn btn-secondary" (click)="cancel()"&gt;取消&lt;/button&gt;
    &lt;button class="btn btn-secondary" (click)="save()"&gt;保存&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;

</code></pre>
<p>crisis-detail.component.ts</p>
<pre><code class="language-js">@Component({
selector: 'app-crisis-detail',
templateUrl: './crisis-detail.component.html',
styles: [
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CrisisDetailComponent implements OnInit {
editName = '';
crisis: Crisis;
constructor(
    private router: Router,
    private route: ActivatedRoute,
    private crisisServe: CrisisService,
    private cdr: ChangeDetectorRef,
    private dialogServe: DialogService) { }
ngOnInit(): void {
    this.route.paramMap.pipe(switchMap(params =&gt; {
      return this.crisisServe.getCrisis(params.get('id'));
    })).subscribe(crisis =&gt; {
      // console.log('cc');
      this.crisis = crisis;
      this.editName = crisis.name;
      this.cdr.markForCheck();
    });
}

cancel() {
    this.gotoCrises();
}

save() {
    this.editName = this.crisis.name;
    this.gotoCrises();
}

gotoCrises() {
    this.router.navigate(['../'], { relativeTo: this.route });
}

canDeactivate() {
    if (!this.crisis || this.crisis.name === this.editName) {
      return true;
    }
    return this.dialogServe.confirm('Discard changes?');
}
}

</code></pre>
<p>dialog.service.ts</p>
<pre><code class="language-js">import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';

@Injectable({
providedIn: 'root',
})
export class DialogService {
/**
   * Ask user to confirm an action. `message` explains the action and choices.
   * Returns observable resolving to `true`=confirm or `false`=cancel
   */
confirm(message?: string): Observable&lt;boolean&gt; {
    const confirmation = confirm(message || 'Is it OK?');
    return of(confirmation);
}
}
</code></pre>
<h2 id="resolve">Resolve</h2>
<p>进入组件前获取数据</p>
<p>crisis-detail-resolver.service.ts</p>
<pre><code class="language-js">import { Injectable } from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
import {Crisis} from './crisis';
import {EMPTY, Observable, of} from 'rxjs';
import {CrisisService} from './crisis.service';
import {first, mergeMap} from 'rxjs/operators';

@Injectable({
providedIn: 'root'
})
export class CrisisDetailResolverService implements Resolve&lt;Crisis&gt;{

constructor(private crisisServe: CrisisService, private router: Router) { }

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable&lt;Crisis | never&gt; {
    return this.crisisServe.getCrisis(route.paramMap.get('id')).pipe(
      first(),//转换为一个有限的流
      mergeMap(crisis =&gt; {
      if (crisis) {
          console.log('找到了crisis');
          return of(crisis);
      } else { // 没找到具体的Crisis
          this.router.navigate(['/crisis-center']);
          return EMPTY; //返回empty则取消导航
      }
      })
    );
}
}

</code></pre>
<p>crisis.service.ts</p>
<pre><code class="language-js">import {Observable, of} from 'rxjs';
import { Injectable } from '@angular/core';
import {CRISES} from './mock-crises';
import {Crisis} from './crisis';
import {map} from 'rxjs/operators';
import {Hero} from '../heroes/hero';

@Injectable({
providedIn: 'root',
})
export class CrisisService {
constructor() { }
getCrises(): Observable&lt;Crisis[]&gt; {
    return of(CRISES);
}

getCrisis(id: number | string): Observable&lt;Crisis&gt; {
    return this.getCrises().pipe(
      map((crises: Crisis[]) =&gt; crises.find(crisis =&gt; crisis.id === +id))
    );
}
}

</code></pre>
<p>crisis-center-routing.module.ts</p>
<pre><code class="language-js">const routes: Routes = [
{
    path: '',
    component: CrisisCenterComponent,
    children: [
      {
      path: 'list',
      component: CrisisListComponent,
      children: [
          {
            path: ':id',
            component: CrisisDetailComponent,
            canDeactivate: ,
            resolve: {
            crisis: CrisisDetailResolverService
            },
            data: {
            name: '张三'
            }
          },
          {
            path: '',
            component: CrisisCenterHomeComponent
          }
      ]
      },
      {
      path: '',
      redirectTo: 'list',
      pathMatch: 'full'
      }
    ]
},
];
</code></pre>
<p>crisis-detail.component.ts</p>
<pre><code class="language-js">export class CrisisDetailComponent implements OnInit {
editName = '';
crisis: Crisis;
constructor(
    private router: Router,
    private route: ActivatedRoute,
    private crisisServe: CrisisService,
    private cdr: ChangeDetectorRef,
    private dialogServe: DialogService) { }
ngOnInit(): void {
    this.route.data.subscribe((data: { crisis: Crisis }) =&gt; {
      console.log('data', data);
      this.crisis = data.crisis;
      this.editName = data.crisis.name;
      this.cdr.markForCheck();
    });
}

cancel() {
    this.gotoCrises();
}

save() {
    this.editName = this.crisis.name;
    this.gotoCrises();
}

gotoCrises() {
    this.router.navigate(['../'], { relativeTo: this.route });
}

canDeactivate() {
    if (!this.crisis || this.crisis.name === this.editName) {
      return true;
    }
    return this.dialogServe.confirm('Discard changes?');
}
}
</code></pre>
<h2 id="查询参数及片段">查询参数及片段</h2>
<pre><code class="language-js">checkLogin(url: string): boolean {
    if (this.authService.isLoggedIn) { return true; }

    // Store the attempted URL for redirecting
    this.authService.redirectUrl = url;

    // Redirect to the login page
    return this.router.createUrlTree(['/login'], {
      queryParams: { session_id: 1234567, name: '张三' },
      fragment: 'anchor'
    });
    return false;
}

login() {
    this.message = 'Trying to log in ...';

    this.authService.login().subscribe(() =&gt; {
      this.setMessage();
      if (this.authService.isLoggedIn) {
      const redirectUrl = this.authService.redirectUrl;

      // Redirect the user
      this.router.navigate(, {
             //登录成功后是否保留查询参数和片段
          queryParamsHandling: 'preserve',
          preserveFragment: true
      });
      }
    });
}



checkLogin(url: string): true|UrlTree {
    if (this.authService.isLoggedIn) { return true; }

    // Store the attempted URL for redirecting
    this.authService.redirectUrl = url;

    // Create a dummy session id
    let sessionId = 123456789;
        //跳转同时在地址栏添加
    let navigationExtras: NavigationExtras = {
      queryParams: { 'session_id': sessionId }, //查询参数,?后面内容
      fragment: 'anchor'//片段,#后面的内容
      
      queryParamsHandling:'preserve',
      preeservFragment:true
    };

    // Redirect to the login page with extras
    return this.router.createUrlTree(['/login'], navigationExtras);
}
}

</code></pre>
<p>方法2</p>
<pre><code class="language-js">import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {Observable} from 'rxjs';
import {map} from 'rxjs/operators';
import {SelectivePreloadingStrategyService} from '../../../services/selective-preloading-strategy.service';

@Component({
selector: 'app-admin-dashboard',
template: `
   &lt;div&gt;
   admin-dashboard works!
   &lt;p&gt;Session Id: {{ sessionId | async }}&lt;/p&gt;
   &lt;hr&gt;
   &lt;p&gt;Token: {{ token | async }}&lt;/p&gt;
   &lt;p&gt;
       PreLoad paths: {{ modules }}
   &lt;/p&gt;
   &lt;/div&gt;
`,
styles: [
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AdminDashboardComponent implements OnInit {
sessionId: Observable&lt;string&gt;;
token: Observable&lt;string&gt;;
modules: string[] = [];
constructor(private route: ActivatedRoute, preloadStrategy: SelectivePreloadingStrategyService) {
    this.modules = preloadStrategy.preloadedModules;
}

ngOnInit() {
    // Capture the session ID if available
    this.sessionId = this.route
      .queryParamMap
      .pipe(map(params =&gt; params.get('session_id') || 'None'));

    // Capture the fragment if available
    this.token = this.route
      .fragment
      .pipe(map(fragment =&gt; fragment || 'None'));
}
}

</code></pre>
<h1 id="路由懒加载">路由懒加载</h1>
<h2 id="es6-动态加载懒加载">ES6 动态加载(懒加载)</h2>
<h3 id="标准导入">标准导入</h3>
<pre><code class="language-js">&lt;button (clicl)=alertResult(2,5,3) &gt;&lt;button&gt;
</code></pre>
<pre><code class="language-js">import {add} from './number'

alertResult(...args: number[]) {
    alert(add(args));
}
</code></pre>
<p>number.ts</p>
<pre><code class="language-js">export function add(numbers: number[]) {
return numbers.reduce((prev, curr) =&gt; prev + curr, 0);
}
</code></pre>
<h3 id="动态导入懒加载">动态导入(懒加载)</h3>
<pre><code class="language-js">&lt;button (clicl)=alertResult(2,5,3) &gt;&lt;button&gt;
</code></pre>
<pre><code class="language-js">alertResult(...args: number[]) {
//    import('./number').then(({ default: d, add }) =&gt; {
//      console.log('d', d);
//      alert(add(args));
//    });

        import('./number').then(( module) =&gt; {
      // console.log(' module', module);
       alert(module.add(args));
    });
      
}
</code></pre>
<p>number.ts</p>
<pre><code class="language-js">export function add(numbers: number[]) {
return numbers.reduce((prev, curr) =&gt; prev + curr, 0);
}

//export default ['a', 'b'];
</code></pre>
<h2 id="路由懒加载-1">路由懒加载</h2>
<h3 id="懒加载">懒加载</h3>
<p>app-routing.module.ts (load children)</p>
<pre><code class="language-js">{
path: 'admin',
loadChildren: () =&gt; import('./admin/admin.module').then(m =&gt; m.AdminModule),
},
</code></pre>
<p>最后一步是把管理特性区从主应用中完全分离开。 根模块 <code>AppModule</code> 既不能加载也不能引用 <code>AdminModule</code> 及其文件。</p>
<p>在 <code>app.module.ts</code> 中,从顶部移除 <code>AdminModule</code> 的导入语句,并且从 NgModule 的 <code>imports</code> 数组中移除 <code>AdminModule</code>。</p>
<pre><code class="language-js">const routes: Routes = [
{ path: 'login', loadChildren: () =&gt; import('./pages/login/login.module').then(m =&gt; m.LoginModule) },
{ path: '', redirectTo: '/home/heroes', pathMatch: 'full' },
{ path: '**', redirectTo: '/home/heroes' }
];
</code></pre>
<h3 id="canload">CanLoad</h3>
<ul>
<li>保护对特性模块的未授权加载</li>
</ul>
<p>src/app/auth/auth.guard.ts (CanLoad guard)</p>
<pre><code class="language-js">@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
constructor(private authService: AuthService, private router: Router) {}
canLoad(route: Route, segments: UrlSegment[]): boolean {
    const url = `${route.path}`;
    console.log('canload url', url);
    console.log('canload segments', segments);
    return this.checkLogin(url);
}

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    const url = state.url;
    console.log('canActivate', url);
    return this.checkLogin(url);
}

canActivateChild(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): boolean {
    console.log('canActivateChild');
    return this.canActivate(route, state);
}

checkLogin(url: string): boolean {
    if (this.authService.isLoggedIn) { return true; }

    // Store the attempted URL for redirecting
    this.authService.redirectUrl = url;

    // Redirect to the login page
    this.router.navigate(['/login'], {
      queryParams: { session_id: 1234567, name: '张三' },
      fragment: 'anchor'
    });
    return false;
}
}
</code></pre>
<p>c</p>
<pre><code class="language-js">{
path: 'admin',
loadChildren: () =&gt; import('./admin/admin.module').then(m =&gt; m.AdminModule),
canLoad: //返回true则加载
},
</code></pre>
<h1 id="预加载">预加载</h1>
<p>Router 提供了两种预加载策略:</p>
<ul>
<li>完全不预加载,这是默认值。惰性加载的特性区仍然会按需加载。</li>
<li>预加载所有惰性加载的特性区。</li>
</ul>
<p>c</p>
<pre><code class="language-js">RouterModule.forRoot(
appRoutes,
{
    enableTracing: true, // &lt;-- debugging purposes only
    preloadingStrategy: PreloadAllModules
}
)

@NgModule({
imports: [RouterModule.forRoot(routes,{
                   //enableTracing: true,
                   preloadingStrategy: PreloadAllModules
                  }),      
],
exports:
})
</code></pre>
<h3 id="自定义预加载策略">自定义预加载策略</h3>
<p>src/app/app-routing.module.ts (route data preload)</p>
<pre><code class="language-js">{
path: 'crisis-center',
loadChildren: () =&gt; import('./crisis-center/crisis-center.module').then(m =&gt; m.CrisisCenterModule),
data: { preload: true }//只加载preload为true的模块
},
</code></pre>
<h1 id="路由器事件">路由器事件</h1>
<p><code>Router</code> 在每次导航过程中都会通过 <code>Router.events</code> 属性发出导航事件。这些事件的范围贯穿从导航开始和结束之间的多个时间点。导航事件的完整列表如下表所示。</p>
<table>
<thead>
<tr>
<th style="text-align: left">路由事件</th>
<th style="text-align: left">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left"><code>NavigationStart</code></td>
<td style="text-align: left">导航开始时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>RouteConfigLoadStart</code></td>
<td style="text-align: left">在 <code>Router</code> 惰性加载路由配置之前触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>RouteConfigLoadEnd</code></td>
<td style="text-align: left">在某个路由已经惰性加载完毕时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>RoutesRecognized</code></td>
<td style="text-align: left">当路由器解析了 URL,而且路由已经识别完毕时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>GuardsCheckStart</code></td>
<td style="text-align: left">当路由器开始进入路由守卫阶段时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>ChildActivationStart</code></td>
<td style="text-align: left">当路由器开始激活某路由的子路由时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>ActivationStart</code></td>
<td style="text-align: left">当路由器开始激活某个路由时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>GuardsCheckEnd</code></td>
<td style="text-align: left">当路由器成功结束了路由守卫阶段时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>ResolveStart</code></td>
<td style="text-align: left">当路由器开始路由解析阶段时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>ResolveEnd</code></td>
<td style="text-align: left">当路由器的路由解析阶段成功完成时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>ChildActivationEnd</code></td>
<td style="text-align: left">当路由器成功激活某路由的子路由时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>ActivationEnd</code></td>
<td style="text-align: left">当路由器成功激活了某个路由时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>NavigationEnd</code></td>
<td style="text-align: left">当导航成功结束时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>NavigationCancel</code></td>
<td style="text-align: left">当导航被取消时触发的事件。 这可能在导航期间某个路由守卫返回了 false 或返回了 <code>UrlTree</code> 以进行重定向时发生。</td>
</tr>
<tr>
<td style="text-align: left"><code>NavigationError</code></td>
<td style="text-align: left">当导航由于非预期的错误而失败时触发的事件。</td>
</tr>
<tr>
<td style="text-align: left"><code>Scroll</code></td>
<td style="text-align: left">用来表示滚动的事件。</td>
</tr>
</tbody>
</table>
<p>当启用了 <code>enableTracing</code> 选项时,Angular 会把这些事件都记录到控制台。有关筛选路由器导航事件的示例,请参阅 Angular 中的 Observables 一章的路由器部分。</p>
<h1 id="hash路由">hash路由</h1>
<ul>
<li>history 路由导航</li>
<li>hash 模式导航</li>
</ul>
<pre><code>localhost:3000/crisis-center/

localhost:3000/src/#crisis-center/前面固定,#后面改变
</code></pre>
<p>使用:在app-routing.module.ts中添加useHash:true</p>
<pre><code class="language-js">@NgModule({
imports: [RouterModule.forRoot(routes.concat(namedRoutes), {
    // enableTracing: true,
    //preloadingStrategy: SelectivePreloadingStrategyService
    useHash: true
})],
exports:
})
</code></pre>
<h1 id="查询参数">查询参数</h1>
<h3 id="设置查询参数">设置查询参数</h3>
<p>假设发送 Get 请求时,需要设置对应的查询参数,预期的 URL 地址如下:</p>
<pre><code>https://angular-http-guide.firebaseio.com/courses.json?orderBy="$key"&amp;limitToFirst=1
</code></pre>
<h4 id="创建-httpparams-对象">创建 HttpParams 对象</h4>
<pre><code>import {HttpParams} from "@angular/common/http";

const params = new HttpParams()
    .set('orderBy', '"$key"')
    .set('limitToFirst', "1");

this.courses$ = this.http
    .get("/courses.json", {params})
    .do(console.log)
    .map(data =&gt; _.values(data))
</code></pre>
<p>需要注意的是,我们通过链式语法调用 <code>set()</code> 方法,构建 <code>HttpParams</code> 对象。这是因为 <code>HttpParams</code> 对象是不可变的,通过 <code>set()</code>方法可以防止该对象被修改。</p>
<p>每当调用 <code>set()</code> 方法,将会返回包含新值的 <code>HttpParams</code> 对象,因此如果使用下面的方式,将不能正确的设置参数。</p>
<pre><code>const params = new HttpParams();

params.set('orderBy', '"$key"')
params.set('limitToFirst', "1");
</code></pre>
<p>等效方式</p>
<pre><code>const params = new HttpParams({
fromString: 'orderBy="$key"&amp;limitToFirst=1'
});
</code></pre><br><br>
来源:https://www.cnblogs.com/dingdc/p/14086962.html
頁: [1]
查看完整版本: Angular(4)路由