[]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; }


下篇继续……




posted @ 2016-04-21 23:30  张同光  阅读(84)  评论(0编辑  收藏  举报