Angular学习6-路由

路由是导航的另一个名字。路由器就是从一个视图导航到另一个视图的机制。

1.导航,那么我们专门做一个导航组件。这个组件只是导航使用。一般导航的都是第一个页面,而我们现在启动的就是app.component.ts。
但是此页面目前显示的是列表,我们需要修改下,修改成从主页导航到列表页。

那么我们如此做:
(1)把app.component.ts文件改名为heroes.component.ts。
(2)把AppComponent类改名为HeroesComponent(注意,只在这一个文件中改名)。
(3)把app-test选择器改名为'app-my-heroes'。

2.创建导航页面,即新的app.component.ts。
新的AppComponent将成为应用的“壳”。 它将在顶部放一些导航链接,并且把我们要导航到的页面放在下面的显示区中。
执行下列步骤(请严格按照此步骤做,不能跳):
(1)创建一个名叫src/app/app.component.ts的新文件。
(2)添加支持性的import语句。
(3)定义一个导出的 AppComponent类。
(4)在类的上方添加@Component元数据装饰器,装饰器带有app-test选择器。
(5)将下面的项目从HeroesComponent移到AppComponent:
(5.1)title类属性
(5.2)@Component模板中的

标签,它包含了对title属性的绑定。
(5.3)在模板的标题下面添加标签,以便我们仍能看到英雄列表。
(6)添加HeroesComponent组件到根模块的declarations数组中,以便 Angular 能认识标签。组件都需要添加到此处。
(7)添加HeroService到AppModule的providers数组中,因为我们的每一个视图都需要它。
(8)从HerosComponent的providers数组中移除HeroService,因为它被提到模块了。
(9)为AppComponent添加一些import语句。

实际文件:app.component.ts文件

import { Component } from '@angular/core';

@Component({
  selector: 'app-test',
  template: `
    

{{title}}

//这个就是列表页面 ` }) export class AppComponent { title = 'Tour of Heroes'; }

app.module.ts文件:

import { NgModule }       from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';
import { FormsModule }    from '@angular/forms';

import { AppComponent }        from './app.component';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroesComponent }     from './heroes.component';//包含
import { HeroService }         from './hero.service';//包含

@NgModule({
  imports: [
    BrowserModule,
    FormsModule
  ],
  declarations: [
    AppComponent,
    HeroDetailComponent,
    HeroesComponent//添加这个
  ],
  providers: [//移到此
    HeroService
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule {
}

上面2步其实没有做实际的东西,就是拆成2个组件而已,没有做实际意义的路由的处理。

3.现在开始处理路由:
(1)打开index.html,确保它的区顶部有一个元素
(2)配置路由。app.module.ts中
(2.1)import { RouterModule } from '@angular/router';
(2.2)
imports: [
BrowserModule,
FormsModule, // <-- import the FormsModule before binding with [(ngModel)]
RouterModule.forRoot([//放到这里
{
path: 'heroes',
component: HeroesComponent
}
])
],
(3)修改app.component.ts的模板:
template:

{{title}}

Heroes //显示路由到的组件的内容
这样就可以实现路由了。

注意:这个时候模板中的routerLink的属性值和app.module.ts中的path的关系可以看明白了。这就是路由切换了,比较简单的。

路由定义包括以下部分:
(1)Path: 路由器会用它来匹配浏览器地址栏中的地址,如heroes。
(2)Component: 导航到此路由时,路由器需要创建的组件(HeroesComponent)。

那个forroot是什么意思?下回分解。
4.添加路由,其实很简单,不信,再添加一个试试。
(1)添加一个新文件dashboard.component.ts然后内容写上:

import { Component } from '@angular/core';

@Component({
  selector: 'app-my-dashboard',
  template: '

My Dashboard

' }) export class DashboardComponent { }

(2)配置新的路由:

 RouterModule.forRoot([
      {
        path: 'heroes',
        component: HeroesComponent
      },
      {
        path: 'dashboard',//添加一个这个而已
        component: DashboardComponent
      }
    ])

(3)将新的组件添加到module,这个很简单,大家都应该知道如何添加了。先import { HeroesComponent } from './heroes.component';包含它,然后

 declarations: [
    HeroDetailComponent,
    HeroesComponent,
    AppComponent,
    DashboardComponent//放到这里
  ],

这样就包含了。
(4)这样就算是准备好了。再来,这个是使用:
改变app.component.ts的模板:

template: `
    

{{title}}

Heroes Dashboard `

这样就是两个页面切换了,很简单吧。
注:上面的写法有点啰嗦,可以如此写:

template: `
    

{{title}}

Heroes Dashboard `

5.添加重定向,让启动就显示一个组件:

 RouterModule.forRoot([
      {
        path: 'heroes',
        component: HeroesComponent
      },
      {
        path: 'dashboard',
        component: DashboardComponent
      },
      {
        path: '',//路径是根
        redirectTo: '/dashboard',//重定向了
        pathMatch: 'full'
      }
    ])

也是很简单的。
6.美化下dashboard.component这个组件:
(1)dashboard.component.ts文件修改为:

import { Component, OnInit } from '@angular/core';

import { Hero } from './hero';
import { HeroService } from './hero.service';//包含service

@Component({
  selector: 'app-my-dashboard',
  templateUrl: './dashboard.component.html',//使用文件显示
})
export class DashboardComponent implements OnInit {

      heroes: Hero[] = [];

      constructor(private heroService: HeroService) { }//构造方法申明私有变量

      ngOnInit(): void {//初始化,使用承诺接口
        this.heroService.getHeroes()
          .then(heroes => this.heroes = heroes.slice(1, 5));
      }
    }

(2)添加dashboard.component.html文件,内容如下:

Top Heroes

{{hero.name}}

美化完成了。数据使用的服务的数据。

7.路由到详情,并传递数据。前面到详情页面,是使用的这种方式来传递对象的。现在,我们使用路由的方式导航到详情页面,现在开始改造:
(1)在app.module.ts中做一个参数化的路由:

{
        path: 'detail/:id',//路径中的冒号 (:) 表示:id是一个占位符,当导航到这个HeroDetailComponent组件时,它将被填入一个特定英雄的id。
        component: HeroDetailComponent
      }

(2)改造hero-detail.component.ts为:

// Keep the Input import for now, you'll remove it later:
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { Location } from '@angular/common';

import { HeroService } from './hero.service';
import 'rxjs/add/operator/switchMap';
import { Hero } from './hero';


@Component({
    selector: 'app-hero-detail',
    templateUrl: './hero-detail.component.html',//模板变化
  })

export class HeroDetailComponent implements OnInit {
    constructor(
        private heroService: HeroService,
        private route: ActivatedRoute,
        private location: Location
      ) {}

      @Input() hero: Hero;

      ngOnInit(): void {
        this.route.paramMap
          .switchMap((params: ParamMap) => this.heroService.getHero(+params.get('id')))
          .subscribe(hero => this.hero = hero);
      }

      goBack(): void {
        this.location.back();//利用浏览器的历史堆栈,导航到上一步
      }
}

switchMap运算符如何将可观察的路由参数中的 id 映射到一个新的Observable, 即HeroService.getHero()方法的结果。

如果用户在 getHero 请求执行的过程中再次导航这个组件,switchMap 再次调用HeroService.getHero()之前, 会取消之前的请求。

英雄的id是数字,而路由参数的值总是字符串。 所以我们需要通过 JavaScript 的 (+) 操作符把路由参数的值转成数字。
(3)在hero.service.ts中添加:
···
getHero(id: number): Promise {
return this.getHeroes()
.then(heroes => heroes.find(hero => hero.id === id));
}//根据ID获取到信息
···
(4)添加hero-detail.component.html文件:
···


{{hero.name}} details!



{{hero.id}}







···
(5)点击时,需要切到detail页面,需要改造dashboard.component.html,能够点击和传递参数:

Top Heroes

现在就可以用路由的方式导航到detail页面了。还能传递参数呢。

8.上面虽然可以使用了,但是路由的代码太多,让app.module.ts会越变越大,因此,需要将路由提取到一个单独的文件。
(1)做一个单独的文件:app-routing.module.ts并写代码为:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { DashboardComponent } from './dashboard.component';
import { HeroesComponent } from './heroes.component';
import { HeroDetailComponent } from './hero-detail.component';

const routes: Routes = [
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  { path: 'dashboard',  component: DashboardComponent },
  { path: 'detail/:id', component: HeroDetailComponent },
  { path: 'heroes',     component: HeroesComponent }
];//以后添加路由添加到此即可。

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

(2)修改app.module.ts,以便包含这个路由:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here

import { AppComponent } from './app.component';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroesComponent } from './heroes.component';
import { DashboardComponent } from './dashboard.component';
import { HeroService } from './hero.service';

import { AppRoutingModule } from './app-routing.module';//1、包含它

@NgModule({
  imports: [
    BrowserModule,
    FormsModule, // <-- import the FormsModule before binding with [(ngModel)]
    AppRoutingModule//2.放到此,添加模块
  ],
  declarations: [
    HeroDetailComponent,
    HeroesComponent,
    AppComponent,
    DashboardComponent,
  ],
  bootstrap: [ AppComponent ],
  providers: [HeroService]
})
export class AppModule { }

通过上面2步,就将路由单独列出了。

9.也可以通过代码跳转到详细页面,当然也是路由的方式。
(1).将heroes.component.ts中模板中的:

替换成一个按钮:

{{selectedHero.name | uppercase}} is my hero

//这个按钮

(2)在类中:

import { Router } from '@angular/router';//1.包含

constructor(
    private router: Router,
    private heroService: HeroService) { }//2.构造函数中申明

 gotoDetail(): void {
    this.router.navigate(['/detail', this.selectedHero.id]);//3.使用代码跳转
  }

你可能感兴趣的:(Angular学习6-路由)