angular+ 路由学习 (四)子路由学习

  • 在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 组件是在为空的情况下显示;有图可以方便理解;

猜你喜欢

转载自www.cnblogs.com/gushiyoyo/p/11265590.html