- 在app目录下新建crisis-center文件夹/目录
- 使用命令新建路由和组件
// 在crisis-center目录下新建路由组件 ng g module crisis-center/crisis-center --module --flat --routing // 在某目录下新建组件或服务等命令可为 ng g component <目录名>/<name> //例如: ng g component crisis-center/crisis-center 即在crisis-center目录下新建crisis-center 组件; // 该方法还可以是,使用终端进入到相对应的目录下进行创建 cd src/app/crisis-center ng g component crisis-center
- 当前目录树结构(两个service可以通过 ng g service crisis-center/<name> 来创建)
- 配置路由前,先修改模块主视图结构;这里以crisis-center.component 作为主组件,即该模块的父级/顶级,所以在crisis-center.component.html中插入占位符;
-
<h2> 危机中心 </h2> <router-outlet></router-outlet>
- 组件已经创建,路由模块也已经创建;接下来就是需要配置路由
-
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { CrisisCenterComponent } from './crisis-center/crisis-center.component'; import { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component'; import { CrisisDetailComponent } from './crisis-detail/crisis-detail.component'; import { CrisisListComponent } from './crisis-list/crisis-list.component'; // CrisisCenterComponent 为模块主组件, 即作为父路由,通过children 来 定义子路由 // 理解:localhost:4200/crisis-center 为父组件路径,对应 CrisisCenterComponent组件 // localhost:4200/crisis-center/‘’ 将在router-outlet中显示 子组件 CrisisListComponent // localhost:4200/crisis-center/‘’/'' 即CrisisListComponent 的子路由 ,对应 CrisisCenterHomeComponent // localhost:4200/crisis-center/‘’/1 即CrisisListComponent 的子路由 ,对应 CrisisDetailComponent // 因为在顶级,以/开头的路径指向应用的根,而子路由是在父路由路径的基础上的扩展, // 所以在路由树每深入一步,就要在该路由路径上添加一个/符号,后面跟上相对应的路径; // 如果是空,则不添加/符号; // 所以上面要想导航到CrisisCenterHomeComponent,就是localhost:4200/crisis-center ('' 符号前/ 被省略) // 而导航到CrisisDetailComponent,localhost:4200/crisis-center/1 const crisisCenterRoutes: Routes = [ { path: 'crisis-center', component: CrisisCenterComponent, children: [ { path: '', component: CrisisListComponent, children: [ { path: ':id', component: CrisisDetailComponent}, { path: '', component: CrisisCenterHomeComponent} ]} ] } ]; @NgModule({ imports: [RouterModule.forChild(crisisCenterRoutes)], exports: [RouterModule] }) export class CrisisCenterRoutingModule { }
- 路由配置完毕后,将该模块导入到AppModule 中;
- 根据官文;是将hero目录下的文件复制到crisis中,即两者的视图和组件方法是一致的;但对于小白来说还是坑;所以这里贴出代码:
- 根据路由配置可知道,当空路由时,指向 CrisisListComponent 组件;
-
<ul class="crises"> <li *ngFor="let crisis of crises$ | async" [class.selected]="crisis.id === selectedId"> <a [routerLink]="[crisis.id]"> <span class="badge">{{ crisis.id }}</span>{{ crisis.name }} </a> </li> </ul> <!-- 子路由视图占位 --> <router-outlet></router-outlet>
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { CrisisService } from '../crisis.service'; import { Crisis } from '../crisis'; import { Observable } from 'rxjs'; import { switchMap } from 'rxjs/operators'; @Component({ selector: 'app-crisis-list', templateUrl: './crisis-list.component.html', styleUrls: ['./crisis-list.component.css'] }) export class CrisisListComponent implements OnInit { crises$: Observable<Crisis[]>; selectedId: number; constructor( private service: CrisisService, private route: ActivatedRoute ) { } ngOnInit() { this.crises$ = this.route.paramMap.pipe( switchMap(params => { this.selectedId = +params.get('id'); return this.service.getCrises(); }) ); } }
- cirisis-detail组件视图
-
<h2>crisisES</h2> <div *ngIf="crisis$ | async as crisis"> <h3>"{{ crisis.name }}"</h3> <div> <label>Id: </label>{{ crisis.id }}</div> <div> <label>Name: </label> <input [(ngModel)]="crisis.name" placeholder="name"/> </div> <p> <button (click)="gotoCrises(crisis)">Back</button> </p> </div>
import { switchMap } from 'rxjs/operators'; import { Component, OnInit, Input } from '@angular/core'; import { Router, ActivatedRoute, ParamMap } from '@angular/router'; // 导入类 import { Observable } from 'rxjs'; import { Crisis } from '../crisis'; import { CrisisService } from '../crisis.service'; @Component({ selector: 'app-crisis-detail', templateUrl: './crisis-detail.component.html', styleUrls: ['./crisis-detail.component.css'] }) export class CrisisDetailComponent implements OnInit { crisis$: Observable<Crisis>; //声明 // 服务注入 constructor( private router: Router, private activatedRoute: ActivatedRoute, private crisisService: CrisisService ) { } ngOnInit() { // ActivatedRoute服务来处理路由的路径和参数;这里接收路由参数ID,获取关联数据 // paramMap; 一个Observable, 包含当前路由的必要参数和可选参数组成的map对象;当这个map值变化,可以使用get(name)获取id参数;然后crisisService获取相关id对应的数据并返回; // switchMap(); 可以取消以前未完成的请求,即发起新ID获取请求时,而service还在接收之前id对应的数据时,switchMap 可以放弃老请求而返回新id 的请求数据; this.crisis$ = this.activatedRoute.paramMap.pipe( switchMap((params: ParamMap) => this.crisisService.getCrisis(params.get('id'))) ); } // 使用相对路径导航,需要提供当前的ActivatedRoute,让路由器知道当前处于路由树的位置 // 使用: 链接参数数组后,添加relativeTo属性,并设置为当前的ActivatedRoute gotoCrises(crisis: Crisis) { let crisisId = crisis ? crisis.id : null; this.router.navigate(['../', { id: crisisId, foo: 'foo' }], { relativeTo: this.activatedRoute }); // 相对路由跳转; } }
- crisis.service
-
import { BehaviorSubject, Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { MessageService } from '../message.service'; import { Crisis } from './crisis'; import { CRISES } from './mock-crises'; @Injectable({ providedIn: 'root', }) export class CrisisService { constructor(private messageService: MessageService) { } getCrises(): Observable<Crisis[]> { // 获取列表数据 // TODO: send the message _after_ fetching the heroes return of(CRISES); } getCrisis(id: number | string) { return this.getCrises().pipe( map(crises => crises.find(crisis => crisis.id === +id)) ); } }
- 主要用到现在两个组件,CrisisCenterHomeComponent 组件是在为空的情况下显示;有图可以方便理解;