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


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


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


春节放假回来玩三国志13玩的不亦乐乎,所以拖了两周,今天继续。

代码照例继承上一篇教程( 点我去看)

正文开始

1、上来仍然是打开命令行,在我们的网页所在目录 angular2-tour-of-heroes下输入 npm start,将网页启动起来,然后开着命令行 别动

2、目前我们的网页内容包含了两个部分,一个是heroes列表的部分,另一个是单击列表中的hero显示的hero details的部分,这两个部分的功能都非常简单,但其实都是可以进行扩展的,所以最好不要放在同一个文件里。 我们之前的代码其实违反了Single Responsibility Principle(单一职能原则)。如果将他们分开的话,便于我们未来进行单独修改、测试以及复用。尽管目前我们只是做的一个小入门教程,但我们还是可以用正确的套路来进行,——尤其是当这个套路非常容易实现的时候。 所以接下来我们在app文件夹下新建一个名叫hero-detail.component.ts的文件,然后创建HeroDetailComponent如下所示:

import {Component} from 'angular2/core'; @Component({ selector: 'my-hero-detail', }) export class HeroDetailComponent { }

在最终将这个文件写好以后,我们就可以将hero detail这部分作为 一个组件,用<my-hero-detail></my-hero-detail>的方式放到其他地方显示出来,如同index.html中的<my-app></my-app>。

原教程对于命名原则做了一些解释,大家可以看一下:
Naming conventions
We like to identify at a glance which classes are components and which files contain components.
Notice that we have an AppComponent in a file named app.component.ts and our new HeroDetailComponent is in a file named hero-detail.component.ts.
All of our component names end in "Component". All of our component file names end in ".component".
We spell our file names in lower dash case (AKA "kebab case") so we don't worry about case sensitivity on the server or in source control.
大概理解一下意思就是,component的 类名就用 驼峰命名法(单词首字母大写),且以"Component"结尾,而文件名第一部分用 kebab case命名法(全小写,并用"-"小横线分割单词),且最后以".component"结尾(当然后面还要有个文件扩展名是.ts)

3、接下来我们给 hero-detail.component.ts中的 @Component增加 template,也就是将之前 app.component.ts里面hero detail部分的template 剪切到这个文件里,这样原来hero detail的部分就 没了。然而这部分template 不能原封不动的挪过来,因为过去的template中hero detail显示的都是 selectedHero的内容,而我们这个文件里 没有selectedHero,所以要做一些修改, 将涉及到selectedHero的部分改为hero,如下所示:

template: ` <div *ngIf="hero"> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name"/> </div> </div> `,


4、接下来我们要再做一次分离的操作,这回是将 app.component.ts中用来做类型判断的 interface Hero也单独挪出来以便我们以后在多个文件中都使用它。在 app文件夹里新建一个叫 hero.ts的文件,然后将 app.component.ts中的 interface Hero剪切到这里,并在interface前面加上 export(有这个export,我们才能在其他文件中import它),如下所示:

export interface Hero { id: number; name: string; }


5、之后我们需要在 app.component.tshero-detail.component.ts引入这个interface,这样才能像原来一样使用它,在这两个文件的import部分,加上这一行:

import {Hero} from './hero';


6、接下来我们回到 hero-detail.component.ts,处理一下 hero,我们先在 class里增加一个 hero变量,如下所示:

export class HeroDetailComponent { hero: Hero; }


7、接下来我们要想了,如何获得这个hero以便它显示到template?我们知道,这个hero过去是selectedHero,也就是说我们单击了列表中的某个hero以后才会将单击的hero对象传到selectedHero,所以它的来源其实是 app.component.ts。打开 app.component.ts,在 template中原hero detail的地方(现在应该没了,因为已经剪切到了hero-detail.component.ts里了)增加这么一行:

<my-hero-detail [hero]="selectedHero"></my-hero-detail>


8、按照惯例,我们既然在 app.component.ts里引用了hero-detail组件,就需要在最开始 import它,在 app.component.ts的 import的部分加入如下所示代码:

import {HeroDetailComponent} from './hero-detail.component';

这样my-hero-detail就变成了my-app组件中的 子组件,我们在index.html中显示了<my-app></my-app>,而<my-app></my-app>中又包含了他的template和<my-hero-detail></my-hero-detail>。

这里我们可以看到my-hero-detail获取hero的方法是一个 单向数值绑定,你可能还有印象在app.component.ts中的class里我们对selectedHero做过处理,我们在app.component.ts中通过单击列表中的hero触发了 onSelect事件将单击的hero传给了selectedHero变量,这里我们将selectedHero又传给了组件my-hero-detail中的hero变量,然后my-hero-detail中的hero又显示到了hero-detail.component.ts中的template。

9、然而,光这么做还不够,我们还需要在 hero-detail.component.ts里指明,哪个变量是 input进来的。所以我们需要在hero-detail.component.ts中的@Component里加上这么一行:

inputs: ['hero']

现在app.component.ts的template,应该是下面这个样子:

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> <my-hero-detail [hero]="selectedHero"></my-hero-detail> `,


10、理论上来讲,我们现在应该已经大功告成,然而当我们等页面刷新到修改以后,单击某个hero发现,该有的detail 并没有出现,chrome的控制台 也没有任何报错。这是因为, Angular没有识别<my-hero-detail></my-hero-detail>这个组件,我们import了HeroDetailComponent,在template里使用了它,所以我们需要 通知Angular,而这一步非常简单,只需要在 app.component.ts@Componenttemplate和style后面加入这么一行代码就行了:

directives: [HeroDetailComponent]

等一会页面自动刷新,就可以看到最终结果了。

结尾给一下全部的代码,如果跟着步骤有什么问题可以参照一下:

app/hero-detail.component.ts

import {Component} from 'angular2/core'; import {Hero} from './hero'; @Component({ selector: 'my-hero-detail', template: ` <div *ngIf="hero"> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name"/> </div> </div> `, inputs: ['hero'] }) export class HeroDetailComponent { hero: Hero; }


app/app.component.ts

import {Component} from 'angular2/core'; import {Hero} from './hero'; import {HeroDetailComponent} from './hero-detail.component'; @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> <my-hero-detail [hero]="selectedHero"></my-hero-detail> `, 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; } `], directives: [HeroDetailComponent] }) export class AppComponent { title = 'Tour of Heroes'; heroes = HEROES; 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" } ];

app/hero.ts

export interface Hero { id: number; name: string; }


下篇继续……




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