在本页面,你将扩展《英雄指南》应用,让它显示一个英雄列表, 并容许用户选择一个英雄,查看该英雄的详细信息。css
你须要一些英雄数据以供显示。html
最终,你会从远端的数据服务器获取它。可是目前,你须要建立一些模拟英雄(some mock heroes),并假设这些数据是从远程服务器上获取的。git
在 src/app/
文件夹中建立一个名叫 mock-heroes.ts
的文件。 定义一个包含十个英雄的常量数组 HEROES
,并导出它。 该文件是这样的。github
src/app/mock-heroes.tsapi
|
你要在 HeroesComponent
的顶部显示这个英雄列表。
打开 HeroesComponent
类文件,并导入模拟的 HEROES 数据。
src/app/heroes/heroes.component.ts
|
往类中添加一个 heroes
属性,这样能够暴露出这些英雄,以供绑定。
src/app/heroes/heroes.component.ts
|
*
ngFor 列出这些英雄打开 HeroesComponent
的模板文件,并作以下修改:
<h2>
<ul>
)<ul>
中插入一个 <li>
元素,以显示单个 hero
的属性。完成后应该以下显示:
heroes.component.html
|
如今,把 <li>
修改为这样:
|
*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
|
打开 heroes.component.css
文件,而且把 HeroesComponent
的私有 CSS 样式粘贴进去。 你能够在本指南底部的查看最终代码中找到它们。
@
Component 元数据中指定的样式和样式表都是局限于该组件的。 heroes.component.css
中的样式只会做用于 HeroesComponent
,既不会影响到组件外的 HTML,也不会影响到其它组件中的 HTML。
当用户在主列表中点击一个英雄时,该组件应该在页面底部显示所选英雄的详情。
在本节,你将监听英雄条目的点击事件,并更新英雄的详情。
click
事件绑定再往 <li>
元素上插入一句点击事件的绑定代码:
heroes.component.html
|
这是 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
|
该模板引用的仍然是老的 hero
属性,但它已经不存在了。 把 hero
更名为 selectedHero
。
heroes.component.html
|
刷新浏览器,应用挂了。
打开浏览器的开发者工具,它的控制台中显示出以下错误信息:
|
当应用启动时,selectedHero
是 undefined
,设计如此。
但模板中的绑定表达式引用了 selectedHero
的属性(表达式为 {{
selectedHero.name}}
),这必然会失败,由于你还没选过英雄呢。
如今,从列表中随便点击一个条目。 应用又正常了。 英雄们显示在列表中,而且所点英雄的详情也显示在了页面的下方。
该组件应该只有当 selectedHero
存在时才显示所选英雄的详情。
把显示英雄详情的 HTML 包裹在一个 <div>
中。 而且为这个 div 添加 Angular 的 *
ngIf 指令,把它的值设置为 selectedHero
。
不要忘了 ngIf 前面的星号(*
),它是该语法中的关键部分。
src/app/heroes/heroes.component.html (*ngIf)
|
浏览器刷新以后,英雄名字的列表又出现了。 详情部分仍然是空。 点击一个英雄,它的详情就出现了。 这个应用看起来又再次工做正常显示了。 英雄显示在列表中,当你单击英雄的名字的时候,有关你单击英雄的详细信息就显示在页面的底部了。
当 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)
|
若是当前行的英雄和 selectedHero
相同,Angular 就会添加 CSS 类 selected
,不然就会移除它。
最终的 <li>
是这样的:
heroes.component.html (list item hero)
|
下面是本页面中所说起的代码文件,包括 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