Angular 显示英雄列表
在本页面,你将扩展《英雄指南》应用,让它显示一个英雄列表, 并允许用户选择一个英雄,查看该英雄的详细信息。
创建模拟(mock)英雄数据
你需要一些英雄数据以供显示。
最终,你会从远端的数据服务器获取它。但是目前,你需要创建一些模拟英雄(some mock heroes),并假设这些数据是从远程服务器上获取的。
在 src/app/
文件夹中创建一个名叫 mock-heroes.ts
的文件。 定义一个包含十个英雄的常量数组 HEROES
,并导出它。 该文件是这样的。
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 数据。
import { HEROES } from '../mock-heroes' ; |
往类中添加一个 heroes
属性,这样可以暴露出这些英雄,以供绑定。
export class HeroesComponent implements OnInit { heroes = HEROES; |
使用 *
ngFor 列出这些英雄
打开 HeroesComponent
的模板文件,并做如下修改:
- 在顶部添加
<h2>
- 然后添加表示无序列表的 HTML 元素(
<ul>
) - 在
<ul>
中插入一个<li>
元素,以显示单个hero
的属性。 - 点缀上一些 CSS 类(稍后你还会添加更多 CSS 样式)。
完成后应该如下显示:
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 指向它,就像这样:
@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>
元素上插入一句点击事件的绑定代码:
<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
属性。
selectedHero: Hero; onSelect(hero: Hero): void { this .selectedHero = hero; } |
修改详情模板
该模板引用的仍然是老的 hero
属性,但它已经不存在了。 把 hero
改名为 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> |
刷新浏览器,应用挂了。
打开浏览器的开发者工具,它的控制台中显示出如下错误信息:
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 前面的星号(
*
),它是该语法中的关键部分。
<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]
绑定,代码如下:
[ class .selected]= "hero === selectedHero" |
如果当前行的英雄和 selectedHero
相同,Angular 就会添加 CSS 类 selected
,否则就会移除它。
最终的 <li>
是这样的:
<li *ngFor= "let hero of heroes" [ class .selected]= "hero === selectedHero" (click)= "onSelect(hero)" > <span class = "badge" >{{hero.id}}</span> {{hero.name}} </li> |
查看最终代码
下面是本页面中所提及的代码文件,包括 HeroesComponent
的样式。
对应的文件列表和代码链接如下:
文件名
|
源代码
|
---|---|
src/app/heroes/heroes.component.ts | https://github.com/cwiki-us-angular/cwiki-us-angular-tour-of-heroes-list/blob/master/src/app/heroes/heroes.component.ts |
src/app/heroes/heroes.component.html | https://github.com/cwiki-us-angular/cwiki-us-angular-tour-of-heroes-list/blob/master/src/app/heroes/heroes.component.html |
src/app/heroes/heroes.component.css | https://github.com/cwiki-us-angular/cwiki-us-angular-tour-of-heroes-list/blob/master/src/app/heroes/heroes.component.css |
小结
- 英雄指南应用在一个主从视图中显示了英雄列表。
- 用户可以选择一个英雄,并查看该英雄的详情。
- 你使用
*
ngFor 显示了一个列表。 - 你使用
*
ngIf 来根据条件包含或排除了一段 HTML。 - 你可以用
class
绑定来切换 CSS 的样式类。
https://www.cwiki.us/display/AngularZH/Display+a+Heroes+List
Angular 显示英雄列表的更多相关文章
- [nodejs,expressjs,angularjs2] LOL英雄列表数据抓取及查询显示应用
新手练习,尝试使用angularjs2 [angularjs2 数据绑定,监听数据变化自动修改相应dom值,非常方便好用,但与传统js(jquery)的使用方法会很不同,Dom操作也不太习惯] 应用效 ...
- 12-27cell 的可重用性(英雄列表应用性能的优化)
在英雄列表中动态生成cell的代码在中, - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N ...
- Laravel大型项目系列教程(四)显示文章列表和用户修改文章
小编心语:不知不觉已经第四部分了,非常感谢很多人给小编提的意见,改了很多bug,希望以后能继续帮小编找找茬~小编也不希望误导大家~这一节,主要讲的 是如何显示文章列表和让用户修改文章,小编预告一下(一 ...
- 一段显示隐藏列表HTML代码
一段显示隐藏列表HTML代码, 技巧在于把页面上的元素(“返回首页”)和控制显示/隐藏的元素(id=navs-menu)放在一个共同的div上,并在该div上绑定onmouseover和onmouse ...
- centos中设置apache显示目录列表
apache中显示目录列表 在http.conf中加入如下代码(如有虚拟主机配置,加在虚拟主机配置段内),并把主目录内的index.pho,index.html,index.htm文件删除 复制代码 ...
- wxPython制作跑monkey工具(python3)-带显示设备列表界面
一. wxPython制作跑monkey工具(python3)-带显示设备列表界面 源代码 Run Monkey.py #!/usr/bin/env python import wx import ...
- sublime text 格式化html css 与显示函数列表
sublime 格式化html css 1.ctrl + shift + p 2.输入install package,选择install package 3.输入:HTML-CSS-JS Pretti ...
- Struts2(六.用标签显示用户列表及Value Stack和Stack Context)
一.用Struts2标签显示用户列表 原理: 在struts中可以通过在action中将所有用户的信息存入到某个范围中,然后转向userlist.jsp,进行访问 原则: 在jsp网页上,尽量不要出现 ...
- 扩展AutoCompleteTextView让其默认显示一组列表。setThreshold
很多时候, 在做自动下拉框时,默认点上去时需要显示一组默认的下拉数据.但是默认的AutoCompleteTextView是实现不了的, 因为setThreshold方法最小值是1,就算你设的值为0,也 ...
随机推荐
- get传数组
开发真的处处都是坑呀 ajax get请求,传数组,想当然的给了个json数组['','',''],结果500错误 正确的方式,多次赋值,见下图,后台会自动转数组
- P1002 过河卒 【递推、简单动规】
题目描述 棋盘上AA点有一个过河卒,需要走到目标BB点.卒行走的规则:可以向下.或者向右.同时在棋盘上CC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒 ...
- 针对mdadm的RAID1失效测试
背景 对软RAID(mdadm)方式进行各个场景失效测试. 一.初始信息 内核版本: root@omv30:~# uname -a Linux omv30 4.18.0-0.bpo.1-amd64 # ...
- 1. Python中的基本数据类型、运算、变量
本文利用的是Python 3.x版本,建议学习3.x版本 Python中的基本数据类型.运算.变量 1. 基本数据类型 1.1 整数 py可以处理任意大小的整数,例如123,1234567891324 ...
- 关于单片机编程里面调用sprintf死机的解决方法及原因分析
好久之前的做的笔记,这里贴出. char String[100];//直接用数组代替指针即可解决 下面代代码下载至单片机中,发现会出现单片机死机问题 #include "stdio.h&qu ...
- Vue中数据的处理
临时变量参数的存储 1.引用类型和值类型的差异,及存储 2.在项目中做的绑定值,首先v-model 存储到临时变量,同时把数据在提交到api之前,需要做处理,因为是引用类型的数据,在处理之前,会修改掉 ...
- opencv图像阈值设置的三种方法
1.简单阈值设置 像素值高于阈值时,给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色).这个函数就是 cv2.threshhold().这个函数的第一个参数就是原图像 ...
- CodeForces - 357D - Xenia and Hamming
先上题目: D. Xenia and Hamming time limit per test 1 second memory limit per test 256 megabytes input st ...
- 华为USG6350防洪墙SNMP最简单功能配置
https://www.cnblogs.com/vincent-liang/p/7785089.html
- hdu_1048_The Hardest Problem Ever_201311052052
The Hardest Problem Ever Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...