[翻译]angularjs 2.0官方新手入门教程(3)


http://alvinwei.blog.163.com/blog/static/214666110201616101635843/


2016-02-07 01:13:24|  分类: AngularJS2.0 |  标签:前端  angular  angularjs2.0  javascript  入门教程   


本来说春节放假回来再翻译后面的,结果今天抽空又翻译了一篇。

注:本篇教程代码承接上一篇教程 点我去看

正文开始

1、上回我们已经能够用一个输入框去修改class里hero的name并显示出来,这篇继续做一些更复杂的事情。 首先让我们先把网页启动起来,打开命令行,进入到网页所在的目录angular2-tour-of-heroes下输入npm start,成功启动网页后,不要关闭命令行。

2、这次我们希望显示很多个hero而不是仅仅只有一个,所以我们要创建一个数组,打开 app.component.ts,在 最下面,也就是class AppComponent的外面,定义一个 HEROES数组,如下所示:

var 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" } ];


3、接下来在 class AppComponent 里使用刚才定义的数组,创建一个变量叫做 heroes ,如下所示:

public heroes = HEROES;


4、下面我们要将这个数组显示出来,将下面的代码粘贴到 @Componenttemplate中的title下面

<h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="#hero of heroes"> <!-- each hero goes here --> </li> </ul>

这里我们可以看到<li>标签里的ngFor就是用来显示heroes数组的,而里面的 (*)星号(#)井号是必不可少的,这里给一下官方对 *ngFor="#hero of heroes"的解释:

The (*) prefix to ngFor indicates that the <li> element and its children constitute a master template.
The ngFor directive iterates over the heroes array returned by the AppComponent.heroes property and stamps out instances of this template.
The quoted text assigned to ngFor means “take each hero in the heroes array, store it in the local hero variable, and make it available to the corresponding template instance”.
The # prefix before "hero" identifies the hero as a local template variable. We can reference this variable within the template to access a hero’s properties.

大概连翻译带解释一下,(*)放在ngFor前面代表 <li>标签里面的内容会构成一个 模板,ngFor从class AppComponent里取出heroes数组,并 遍历里面每个元素后用这个模板显示出来"#hero of heroes"的意思是从heroes里取出 每个hero对象,把他们赋给每个模板中的(#)井号后面所写的本地变量里,在这里就是#hero, 这样每个模板中都有一个hero,但其实他们对应的是从class AppComponent中的heroes数组里取出的不同的hero对象。(#)放到hero前面就是将hero作为接收hero对象的变量名,这样我们可以在这个模板里通过这个变量名获取对应对象的属性进行操作,比如显示他的id,就是{{hero.id}},那假如我们把#hero of heroes修改成#evil of heroes,那么在使用的时候我们就需要将{{hero.id}}改成{{evil.id}}。

5、上面的话听着有点绕,其实很好理解,比如我们现在要 显示每一个hero的id和name,只需要将刚才代码中的 <li> 标签里的内容修改成这个样子:

<li *ngFor="#hero of heroes"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li>

等待页面自动刷新,我们就可以看到更新后的页面显示出所有的英雄id和name了。现在,我们可以用 Chrome检查元素去看一下这个列表的 Elements,虽然我们 只写了一个<li>标签,但是因为ngFor的遍历,会有 很多个<li>标签显示出来,并且每个<li>里面的<span>对应的是 不同的hero。因为<li>及其子元素<span>作为一个模板,被每个遍历后的hero套用很多次并显示出来。

6、刚才你也许发现 <span>标签里有 cssclass,但我们并没有写任何css,所以现在我们就做这个东西,复制下面的css代码到 app.component.ts 中的 @Component

styles:[` .selected { background-color: #CFD8DC !important; color: white; } .heroes { margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 10em; } .heroes li { cursor: pointer; position: relative; left: 0; background-color: #EEE; margin: .5em; padding: .3em 0em; height: 1.6em; border-radius: 4px; } .heroes li.selected:hover { color: white; } .heroes li:hover { color: #607D8B; background-color: #EEE; left: .1em; } .heroes .text { position: relative; top: -3px; } .heroes .badge { display: inline-block; font-size: small; color: white; padding: 0.8em 0.7em 0em 0.7em; background-color: #607D8B; line-height: 1em; position: relative; left: -1px; top: -4px; height: 1.8em; margin-right: .8em; border-radius: 4px 0px 0px 4px; } `]

你会发现我们又一次使用了 (`)符号,以便将css多行显示。
注意:我们在 @Component里定义的这个css并不会在别的地方起效果,他只作用于这个 AppComponent

7、下面我们给 <ul>标签也加上我们刚才写的css样式,最终如下所示:

<h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="#hero of heroes"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul>

等待页面自动刷新,我们就可以看到换上新样式的hero列表了。

8、接下来我们想要跟这个列表的元素进行互动,所以我们要给每个元素加上一个 click事件,如下所示

<li *ngFor="#hero of heroes" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li>

这里的 (click)="onSelect(hero)"代表了当我们点击某一个<li>标签时,会调用一个 onSelect的函数,并将被点击的<li>标签中存储的那个 hero对象作为参数传进去,()小括号在这里代表一个one way(单向)的data binding(数据绑定),方向是将hero传给onSelect函数。

9、我们目前还没有 onSelect这个函数,这个函数的用途是把我们在页面上 单击的<li>中的hero传给 class AppComponent里的一个叫 selectedHero的变量,这样我们就可以在这个类中使用这个selectedHero。所以我们首先要添加一个selectedHero变量。在 class AppComponent里添加 selectedHero变量,就像之前添加heroes一样

public selectedHero: Hero;

这个变量并不用初始化,因为最开始也没有hero被选择。

10、接下来我们要写 onSelect这个函数了,在 class AppComponent里,只需要一行:

onSelect(hero: Hero) { this.selectedHero = hero; }

这样我们选择的那个hero对象就传给了selectedHero。

11、接下来我们要做的是把 selectedHeroidname显示出来,修改上一篇教程中template的html代码,如下所示:

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

这个代码有个问题,等页面自动刷新过后,我们发现 什么都显示不出来。通过Chrome的console会发现报错说“EXCEPTION: TypeError: Cannot read property 'name' of undefined in [null]”,原因是我们 没有给selectedHero赋初值,那么网页刚加载完以后selectedHero就是 null,他的id和name属性自然也就是 undefined

12、要解决这个问题很简单,要么是给selectedHero赋初值,比如heroes的第一个元素。可如果不这么做呢?也很简单,我们需要用一个叫做 ngIf的东西用来判断是不是要处理这块涉及到selectedHero的html代码,所以我们给刚才的代码的 外层加一个<div>标签,并在<div>里加上 ngIf判断一下 selectedHero是否是 null,如下所示:

<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>

这个最外层的<div>的效果就是,如果selectedHero是 null,那么就 移除<div>及其里面的内容,注意,是移除,而不是hide(隐藏)。和ngFor一样, (*)星号在这里必不可少。完成以后,等待一下页面刷新,我们就会看到效果,当没有点击任何hero的时候,这部分页面是不会显示出来的。

13、下面我们想要让被选择的hero所在的<li>看上去和其他的有些区别,之前第5步中的css style里有.selected一项,所以我们只要修改一下<li>标签,让他被选中的时候套用那个css就可以了,所以我们只要给li标签里增加一行代码:

[class.selected]="hero === selectedHero"

这里套在class.selected外面的 []中括号代表这是一个 one-way(单向)的data binding(数据绑定),方向是将data source,即hero === selectedHero的值(true or false) 传回给页面,如果class.selected是true那么就应用style中.selected的样式(关于()小括号和[]中括号,即data binding方向的解释可以看我 上一篇教程的 结尾部分)。接下来等待页面刷新一下就可以看到效果了。

下一篇年后放假回来继续翻译。

最后,放一下这篇教程里 完整的app.component.ts中的代码,如果之前按着教程某些步骤总是达不到预期的效果,可以来参照一下是不是有什么地方写的有问题:

import {Component} from 'angular2/core'; interface Hero { id: number; name: string; } @Component({ selector: 'my-app', template:` <h1>{{title}}</h1> <h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="#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> `, styles:[` .selected { background-color: #CFD8DC !important; color: white; } .heroes { margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 10em; } .heroes li { cursor: pointer; position: relative; left: 0; background-color: #EEE; margin: .5em; padding: .3em 0em; height: 1.6em; border-radius: 4px; } .heroes li.selected:hover { color: white; } .heroes li:hover { color: #607D8B; background-color: #EEE; left: .1em; } .heroes .text { position: relative; top: -3px; } .heroes .badge { display: inline-block; font-size: small; color: white; padding: 0.8em 0.7em 0em 0.7em; background-color: #607D8B; line-height: 1em; position: relative; left: -1px; top: -4px; height: 1.8em; margin-right: .8em; border-radius: 4px 0px 0px 4px; } `] }) export class AppComponent { public title = 'Tour of Heroes'; public heroes = HEROES; public selectedHero: Hero; onSelect(hero: Hero) { this.selectedHero = hero; } } var 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" } ];



你可能感兴趣的:([翻译]angularjs 2.0官方新手入门教程(3))