04、Angular 4 教程 - Tour Of Heroes之事件处理

上篇文章我们学习了对象的插值表达式和双向数据绑定,这篇我们将学习一下ngFor与ngIf的写法以及事件的处理方式。

学习目标

这篇文章将实现如下目标:

  • 显示英雄对象的列表
  • 当点击对象的时候,显示该对象的详细信息

 

学习时长

大概5-10分钟

对象数组定义

在组件文件中定义一个对象数组,用以存放HERO的列表

const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];

修改HTML模板进行显示

/workspace/HelloAngular/src/app cat app.component.html
  <h1>{
   
     {
   
     title}}</h1>
  <h2>My Heroes</h2>
  <ul class="heroes">
    <li *ngFor="let hero of heroes">
       <span class="badge">{
   
     {
   
     hero.id}}</span> {
   
     {
   
     hero.name}}
    </li> 
  </ul>
/workspace/HelloAngular/src/app 

这里用到了ngFor语句,这是一条循环语句,它会从组件中取得列表信息heroes,而heroes在app.component.ts中被定义,正是上面设定的HEROES的常量数组,详细参看如下:

/workspace/HelloAngular/src/app cat app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Tour of Heroes';
  heroes = HEROES;
}
export class Hero {
  id: number;
  name: string;
}
const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];
/workspace/HelloAngular/src/app 

结果页面

结果页面显示如下
 

修改样式

因为此处还是用的上个例子的样式,所以可以看到h1还是跟上次一样,我们修改一下样式文件的内容:

/workspace/HelloAngular/src/app cat app.component.css
  .selected {
    background-color:CFD8DC !important;
    color: white;
  }
  .heroes {
    margin: 0 0 2em 0;
    list-style-type: none;
    padding: 0;
    width: 15em;
  }
  .heroes li {
    cursor: pointer;
    position: relative;
    left: 0;
    background-color:EEE;
    margin: .5em;
    padding: .3em 0;
    height: 1.6em;
    border-radius: 4px;
  }
  .heroes li.selected:hover {
    background-color:BBD8DC !important;
    color: white;
  }
  .heroes li:hover {
    color:607D8B;
    background-color:DDD;
    left: .1em;
  }
  .heroes .text {
    position: relative;
    top: -3px;
  }
  .heroes .badge {
    display: inline-block;
    font-size: small;
    color: white;
    padding: 0.8em 0.7em 0 0.7em;
    background-color:607D8B;
    line-height: 1em;
    position: relative;
    left: -1px;
    top: -4px;
    height: 1.8em;
    margin-right: .8em;
    border-radius: 4px 0 0 4px;
  }
/workspace/HelloAngular/src/app 

确认样式修正后的显示
 

添加Click事件对应

为了能够实现点击某个li能够返回具体的信息,我们需要做如下几件事情

  • 在li标签中添加Click事件的对应,并将ngFor的参数传递进去
  • 在组件中定义一个用于保存选择信息的对象
  • 在组件中进行Click事件的对应并保存传过来的对象值
  • 将此值进行ngModel绑定进行显示

HTML页面代码

使用ngIf的原因是为了判空,在为选中时空值会使得出现undefined的问题,代码如下

/workspace/HelloAngular/src/app cat app.component.html
  <h1>{
   
     {
   
     title}}</h1>
  <h2>My Heroes</h2>
  <ul class="heroes">
    <li *ngFor="let hero of heroes" (click)="onSelect(hero)">
       <span class="badge">{
   
     {
   
     hero.id}}</span> {
   
     {
   
     hero.name}}
    </li> 
  </ul>

  <div *ngIf="selectedHero">
    <h2>{
   
     {
   
     selectedHero.name}} details!</h2>
    <div><label>id: </label>{
   
     {
   
     selectedHero.id}}</div>
    <div>
      <label>name: </label>
      <input [(ngModel)]="selectedHero.name" placeholder="name"/>
    </div>
  </div>
/workspace/HelloAngular/src/app

组件侧代码

/workspace/HelloAngular/src/app cat app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Tour of Heroes';
  heroes = HEROES;
  selectedHero: Hero;

  onSelect(hero: Hero): void {
    this.selectedHero = hero;
  }
}
export class Hero {
  id: number;
  name: string;
}
const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];
/workspace/HelloAngular/src/app 

结果的显示

选择第一个HERO,结果如下
 

选中的项目的样式设定

目前还有一个问题就是页面的选中的id为11的HERO和其他的对象没有区别,我们需要给li添加一个样式,具体写法为 [class.selected]=”hero === selectedHero”,表示如果此项目和选中的项目值相同的话就使用selected样式,加上h1的样式,具体代码如下:

/workspace/HelloAngular/src/app cat app.component.css
h1 {
  color:369;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 250%;
}
  .selected {
    background-color:CFD8DC !important;
    color: white;
  }
  .heroes {
    margin: 0 0 2em 0;
    list-style-type: none;
    padding: 0;
    width: 15em;
  }
  .heroes li {
    cursor: pointer;
    position: relative;
    left: 0;
    background-color:EEE;
    margin: .5em;
    padding: .3em 0;
    height: 1.6em;
    border-radius: 4px;
  }
  .heroes li.selected:hover {
    background-color:BBD8DC !important;
    color: white;
  }
  .heroes li:hover {
    color:607D8B;
    background-color:DDD;
    left: .1em;
  }
  .heroes .text {
    position: relative;
    top: -3px;
  }
  .heroes .badge {
    display: inline-block;
    font-size: small;
    color: white;
    padding: 0.8em 0.7em 0 0.7em;
    background-color:607D8B;
    line-height: 1em;
    position: relative;
    left: -1px;
    top: -4px;
    height: 1.8em;
    margin-right: .8em;
    border-radius: 4px 0 0 4px;
  }
/workspace/HelloAngular/src/app 

HTML模板代码如下:

/workspace/HelloAngular/src/app cat app.component.html
  <h1>{
   
     {
   
     title}}</h1>
  <h2>My Heroes</h2>
  <ul class="heroes">
    <li *ngFor="let hero of heroes"  [class.selected]="hero === selectedHero" (click)="onSelect(hero)">
       <span class="badge">{
   
     {
   
     hero.id}}</span> {
   
     {
   
     hero.name}}
    </li> 
  </ul>

  <div *ngIf="selectedHero">
    <h2>{
   
     {
   
     selectedHero.name}} details!</h2>
    <div><label>id: </label>{
   
     {
   
     selectedHero.id}}</div>
    <div>
      <label>name: </label>
      <input [(ngModel)]="selectedHero.name" placeholder="name"/>
    </div>
  </div>
/workspace/HelloAngular/src/app

结果显示如下
 

总结

这篇文章我们学习了如何进行事件的处理,以及ngFor和ngIf的使用方法,在下一章将会关注Angular组件的复用和组件之间的交互。