在本页面,你将扩展《英雄指南》应用,让它显示一个英雄列表, 并允许用户选择一个英雄,查看该英雄的详细信息。

创建模拟(mock)英雄数据

你需要一些英雄数据以供显示。

最终,你会从远端的数据服务器获取它。但是目前,你需要创建一些模拟英雄(some mock heroes),并假设这些数据是从远程服务器上获取的。

在 src/app/ 文件夹中创建一个名叫 mock-heroes.ts 的文件。 定义一个包含十个英雄的常量数组 HEROES,并导出它。 该文件是这样的。

src/app/mock-heroes.ts
import { Hero } from './hero';
 
export 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' }
];

显示英雄

你要在 HeroesComponent 的顶部显示这个英雄列表。

打开 HeroesComponent 类文件,并导入模拟的 HEROES 数据。

src/app/heroes/heroes.component.ts
import { HEROES } from '../mock-heroes';

往类中添加一个 heroes 属性,这样可以暴露出这些英雄,以供绑定。

src/app/heroes/heroes.component.ts
export class HeroesComponent implements OnInit {
 
  heroes = HEROES;

使用 *ngFor 列出这些英雄

打开 HeroesComponent 的模板文件,并做如下修改:

  • 在顶部添加 <h2>
  • 然后添加表示无序列表的 HTML 元素(<ul>
  • 在 <ul> 中插入一个 <li> 元素,以显示单个 hero 的属性。
  • 点缀上一些 CSS 类(稍后你还会添加更多 CSS 样式)。

完成后应该如下显示:

heroes.component.html
heroes.component.html (heroes template)
content_copy
<h2>My Heroes</h2>
<ul class="heroes">
  <li>
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

现在,把 <li> 修改成这样:

<li *ngFor="let hero of heroes">

*ngFor 是一个 Angular 的复写器(repeater)指令。 它会为列表中的每项数据复写它的宿主元素。

在这个例子中

  • <li> 就是 *ngFor 的宿主元素
  • heroes 就是来自 HeroesComponent 类的列表。
  • 当依次遍历这个列表时,hero 会为每个迭代保存当前的英雄对象。

不要忘了 ngFor 前面的星号(*),它是该语法中的关键部分。

浏览器刷新之后,英雄列表出现了。

给英雄们应用样式表

英雄列表应该富有吸引力,并且当用户把鼠标移到某个英雄上和从列表中选中某个英雄时,应该给出视觉反馈。

教程的第一章,你曾在 styles.css 中为整个应用设置了一些基础的样式。 但那个样式表并不包含英雄列表所需的样式。

固然,你可以把更多样式加入到 styles.css,并且放任它随着你添加更多组件而不断膨胀。

但还有更好的方式。你可以定义属于特定组件的私有样式,并且让组件所需的一切(代码、HTML 和 CSS)都放在一起。

这种方式让你在其它地方复用该组件更加容易,并且即使全局样式和这里不一样,组件也仍然具有期望的外观。

你可以用多种方式定义私有样式,或者内联在 @Component.styles 数组中,或者在 @Component.styleUrls 所指出的样式表文件中。

当 CLI 生成 HeroesComponent 时,它也同时为 HeroesComponent 创建了空白的 heroes.component.css 样式表文件,并且让 @Component.styleUrls 指向它,就像这样:

src/app/heroes/heroes.component.ts
@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})

打开 heroes.component.css 文件,并且把 HeroesComponent 的私有 CSS 样式粘贴进去。 你可以在本指南底部的查看最终代码中找到它们。

@Component 元数据中指定的样式和样式表都是局限于该组件的。 heroes.component.css 中的样式只会作用于 HeroesComponent,既不会影响到组件外的 HTML,也不会影响到其它组件中的 HTML。

主从结构

当用户在列表中点击一个英雄时,该组件应该在页面底部显示所选英雄的详情

在本节,你将监听英雄条目的点击事件,并更新英雄的详情。

添加 click 事件绑定

再往 <li> 元素上插入一句点击事件的绑定代码:

heroes.component.html
<li *ngFor="let hero of heroes" (click)="onSelect(hero)">

这是 Angular 事件绑定 语法的例子。

click 外面的圆括号会让 Angular 监听这个 <li> 元素的 click 事件。 当用户点击 <li> 时,Angular 就会执行表达式 onSelect(hero)

onSelect() 是 HeroesComponent 上的一个方法,你很快就要写它。 Angular 会把所点击的 <li> 上的 hero 对象传给它,这个 hero 也就是前面在 *ngFor 表达式中定义的那个。

添加 click 事件处理器

把该组件的 hero 属性改名为 selectedHero,但不要为它赋值。 因为应用刚刚启动时并没有所选英雄

添加如下 onSelect() 方法,它会把模板中被点击的英雄赋值给组件的 selectedHero 属性。

src/app/heroes/heroes.component.ts
selectedHero: Hero;
onSelect(hero: Hero): void {
  this.selectedHero = hero;
}

修改详情模板

该模板引用的仍然是老的 hero 属性,但它已经不存在了。 把 hero 改名为 selectedHero

heroes.component.html
<h2>{{selectedHero.name | uppercase}} Details</h2>
<div><span>id: </span>{{selectedHero.id}}</div>
<div>
  <label>name:
    <input [(ngModel)]="selectedHero.name" placeholder="name">
  </label>
</div>

刷新浏览器,应用挂了。

打开浏览器的开发者工具,它的控制台中显示出如下错误信息:

HeroesComponent.html:3 ERROR TypeError: Cannot read property 'name' of undefined

出现了什么问题?

当应用启动时,selectedHero 是 undefined设计如此

但模板中的绑定表达式引用了 selectedHero 的属性(表达式为 {{selectedHero.name}}),这必然会失败,因为你还没选过英雄呢。

现在,从列表中随便点击一个条目。 应用又正常了。 英雄们显示在列表中,并且所点英雄的详情也显示在了页面的下方。

修复 - 使用 *ngIf 来隐藏空白的细节

该组件应该只有当 selectedHero 存在时才显示所选英雄的详情。

把显示英雄详情的 HTML 包裹在一个 <div> 中。 并且为这个 div 添加 Angular 的 *ngIf 指令,把它的值设置为 selectedHero

不要忘了 ngIf 前面的星号(*),它是该语法中的关键部分。

src/app/heroes/heroes.component.html (*ngIf)
<div *ngIf="selectedHero">
 
  <h2>{{selectedHero.name | uppercase}} Details</h2>
  <div><span>id: </span>{{selectedHero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="selectedHero.name" placeholder="name">
    </label>
  </div>
 
</div>

浏览器刷新之后,英雄名字的列表又出现了。 详情部分仍然是空。 点击一个英雄,它的详情就出现了。 这个应用看起来又再次工作正常显示了。 英雄显示在列表中,当你单击英雄的名字的时候,有关你单击英雄的详细信息就显示在页面的底部了。

为什么这样是正常的

当 selectedHero 为 undefined 时,ngIf 从 DOM 中移除了英雄详情。因此也就不用担心 selectedHero 的绑定了。

当用户选择一个英雄时,selectedHero 也就有了值,并且 ngIf 把英雄的详情放回到 DOM 中。

给所选英雄添加样式

所有的 <li> 元素看起来都是一样的,因此很难从列表中识别出所选英雄

如果用户点击了“Magneta”,这个英雄应该用一个略有不同的背景色显示出来,就像这样:

所选英雄的颜色来自于你前面添加的样式中的 CSS 类 .selected。 所以你只要在用户点击一个 <li> 时把 .selected 类应用到该元素上就可以了。

Angular 的 CSS 类绑定机制让根据条件添加或移除一个 CSS 类变得很容易。 只要把 [class.some-css-class]="some-condition" 添加到你要施加样式的元素上就可以了。

在 HeroesComponent 模板中的 <li> 元素上添加 [class.selected] 绑定,代码如下:

heroes.component.html (toggle the 'selected' CSS class)
[class.selected]="hero === selectedHero"

如果当前行的英雄和 selectedHero 相同,Angular 就会添加 CSS 类 selected,否则就会移除它。

最终的 <li> 是这样的:

heroes.component.html (list item hero)
<li *ngFor="let hero of heroes"
  [class.selected]="hero === selectedHero"
  (click)="onSelect(hero)">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>

查看最终代码

你的应用现在变成了这样:在线例子 / 下载范例

下面是本页面中所提及的代码文件,包括 HeroesComponent 的样式。

对应的文件列表和代码链接如下:

小结

  • 英雄指南应用在一个主从视图中显示了英雄列表。
  • 用户可以选择一个英雄,并查看该英雄的详情。
  • 你使用 *ngFor 显示了一个列表。
  • 你使用 *ngIf 来根据条件包含或排除了一段 HTML。
  • 你可以用 class 绑定来切换 CSS 的样式类。

https://www.cwiki.us/display/AngularZH/Display+a+Heroes+List

Angular 显示英雄列表的更多相关文章

  1. [nodejs,expressjs,angularjs2] LOL英雄列表数据抓取及查询显示应用

    新手练习,尝试使用angularjs2 [angularjs2 数据绑定,监听数据变化自动修改相应dom值,非常方便好用,但与传统js(jquery)的使用方法会很不同,Dom操作也不太习惯] 应用效 ...

  2. 12-27cell 的可重用性(英雄列表应用性能的优化)

    在英雄列表中动态生成cell的代码在中, - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N ...

  3. Laravel大型项目系列教程(四)显示文章列表和用户修改文章

    小编心语:不知不觉已经第四部分了,非常感谢很多人给小编提的意见,改了很多bug,希望以后能继续帮小编找找茬~小编也不希望误导大家~这一节,主要讲的 是如何显示文章列表和让用户修改文章,小编预告一下(一 ...

  4. 一段显示隐藏列表HTML代码

    一段显示隐藏列表HTML代码, 技巧在于把页面上的元素(“返回首页”)和控制显示/隐藏的元素(id=navs-menu)放在一个共同的div上,并在该div上绑定onmouseover和onmouse ...

  5. centos中设置apache显示目录列表

    apache中显示目录列表 在http.conf中加入如下代码(如有虚拟主机配置,加在虚拟主机配置段内),并把主目录内的index.pho,index.html,index.htm文件删除 复制代码  ...

  6. wxPython制作跑monkey工具(python3)-带显示设备列表界面

    一. wxPython制作跑monkey工具(python3)-带显示设备列表界面  源代码 Run Monkey.py #!/usr/bin/env python import wx import ...

  7. sublime text 格式化html css 与显示函数列表

    sublime 格式化html css 1.ctrl + shift + p 2.输入install package,选择install package 3.输入:HTML-CSS-JS Pretti ...

  8. Struts2(六.用标签显示用户列表及Value Stack和Stack Context)

    一.用Struts2标签显示用户列表 原理: 在struts中可以通过在action中将所有用户的信息存入到某个范围中,然后转向userlist.jsp,进行访问 原则: 在jsp网页上,尽量不要出现 ...

  9. 扩展AutoCompleteTextView让其默认显示一组列表。setThreshold

    很多时候, 在做自动下拉框时,默认点上去时需要显示一组默认的下拉数据.但是默认的AutoCompleteTextView是实现不了的, 因为setThreshold方法最小值是1,就算你设的值为0,也 ...

随机推荐

  1. sqlserver 2014 删除主键约束

    truncate table menu SELECT * FROM sys.foreign_keys WHERE referenced_object_id=OBJECT_ID('menu'); --找 ...

  2. CAD把实体放到当前选择集中

    主要用到函数说明: _DMxDrawX::AddCurrentSelect 把实体放到当前选择集中,详细说明如下: 参数 说明 LONGLONG lId 实体id VARIANT_BOOL isSho ...

  3. Android组件化最佳实践 ARetrofit原理

    ARetrofit原理讲原理之前,我想先说说为什么要ARetrofit.开发ARetrofit这个项目的思路来源其实是Retrofit,Retrofit是Square公司开发的一款针对Android网 ...

  4. 计蒜客 疑似病毒 (AC自动机 + 可达矩阵)

    链接 : Here! 背景 : 开始我同学是用 AC自动机 + DP 的方法来做这道题, 这道题的标签是 AC自动机, 动态规划, 矩阵, 按道理来说 AC自动机 + DP 应该是能过的, 但是他不幸 ...

  5. 通过git向github提交项目

    按顺序学习 https://www.cnblogs.com/forget406/p/6045499.html#top https://blog.csdn.net/xiaoputao0903/artic ...

  6. 搭建 Seafile 专属网盘

    准备域名 任务时间:15min ~ 20min 域名注册 如果您还没有域名,可以在腾讯云上选购,过程可以参考下面的视频. 视频 - 在腾讯云上购买域名 域名解析 域名购买完成后, 需要将域名解析到实验 ...

  7. c# 异步执行

    c#异步执行 Action logAction = () => {////执行的操作 }; logAction.BeginInvoke(null, null);

  8. 2.1.6、SparkEnv中创建ShuffleManager

    ShuffleManager负责管理本地以及远程的block数据的shuffle操作. ShffuleManager的创建是在SparkEnv中. // Let the user specify sh ...

  9. Likecloud-吃、吃、吃(洛谷 1508)

    题目背景 问世间,青春期为何物? 答曰:“甲亢,甲亢,再甲亢:挨饿,挨饿,再挨饿!” 题目描述 正处在某一特定时期之中的李大水牛由于消化系统比较发达,最近一直处在饥饿的状态中.某日上课,正当他饿得头昏 ...

  10. ORA-12547错误

    http://www.linuxidc.com/Linux/2013-03/81330p3.htm << good http://www.verydemo.com/demo_c158_i6 ...