The Hero Editor
很久很久以前
所有的故事都有一个开端。我们的故事开始于“快速开始”章节的结尾。
运行这个在线示例。
创建一个名为angular2-tour-of-heroes
的文件夹并按照快速开始的步骤做好准备,构建好文件结构和核心文件。
或者,可以下载快速开始源码
我们应当准备好如下结构:
angular2-tour-of-heroes
├── app
│ ├── app.component.ts
│ └── main.ts
├── node_modules ...
├── typings ...
├── index.html
├── package.json
├── styles.css
├── systemjs.config.js
├── tsconfig.json
└── typings.json
保持app运行
我们想要运行TypeScript编译器,让它监控文件变更,并且运行服务器。为此我们将执行命令:
npm start
这个命令将运行监控模式的编译器,启动服务器,在浏览器中打开app,并保证app在我们不断创建英雄之旅时运行。
展示我们的英雄
我们想要在app中展示英雄数据。
让我们在AppComponent
类中添加两个属性,作为应用名称的title
属性和作为英雄名称“Windstorm”的hero
属性。
export class AppComponent {
title = 'Tour of Heroes';
hero = 'Windstorm';
}
现在我们更新@Component
装饰器的template,使之与这两个新属性进行数据绑定。
template: '<h1>{{title}}</h1><h2>{{hero}} details!</h2>'
这时浏览器会刷新并展示title和hero。
双大括号告诉app从组件读取title
和hero
属性并展示它们。这就是“插值”形式的单向数据绑定。
想要学习更多关于插值的信息,请访问Displaying Data 章节
Hero对象
此时,我们的hero仅仅是个名称,但是它需要更多的属性。让我们把hero
从一个字符串转化成一个类。
创建一个带有id
和name
属性的Hero
类。把它放在app.component.ts
文件的上方,紧接着imoprt语句。
export class Hero {
id: number;
name: string;
}
现在我们有了Hero
类,再重构组件的hero
属性,使之变为Hero
类型。然后初始化id为1
,name为“Windstorm”。
hero: Hero = {
id: 1,
name: 'Windstorm'
};
由于我们把hero从字符串变为了一个对象,我们需要更新template绑定到hero的name
属性。
template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2>'
浏览器将刷新并继续展示hero的name。
添加更多的HTML
展示了名称没有问题,但我们想要看到hero的所有属性。我们将为hero的id
和name
属性各添加一个<div>
。
template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2><div><label>id: </label>{{hero.id}}</div><div><label>name: </label>{{hero.name}}</div>'
哦哟,我们的template字符串变得很长了,我们最好小心一些来避免输入错误。
多行template字符串
我们可以用字符串链接使template更具可读性,但这会让它变得很丑陋。相反,我们可以利用ES2015和TypeScript中模板字符串的优势来理清杂乱的字符串。
仅仅需要把包裹template的引号改为反引号,并且把<h1>
,<h2>
和<div>
元素拆成单独的一行。
template:`
<h1>{{title}}</h1>
<h2>{{hero.name}} details!</h2>
<div><label>id: </label>{{hero.id}}</div>
<div><label>name: </label>{{hero.name}}</div>
`
编辑Hero
现在我们想要在一个textbox中编辑hero的name。
如下用<label>
和<input>
元素重构hero的name:
template:`
<h1>{{title}}</h1>
<h2>{{hero.name}} details!</h2>
<div><label>id: </label>{{hero.id}}</div>
<div>
<label>name: </label>
<input value="{{hero.name}}" placeholder="name">
</div>
`
我们可以看到浏览器中hero的name显示在<input>
textbox中。但是有个问题,当我们修改name时,<h2>
中并没有实时变更name。然而对<input>
进行单向数据绑定是无法完成这个行为的。
双向数据绑定
我们希望将hero的name展示在<input>
中,修改它,然后可以看到绑定到hero.name的元素都跟着变化。简单的说,我们想要双向数据绑定。
让我们用ngModel
这个内置指令修改template来实现双向绑定。
想要学习更多关于
ngModel
的只是,请访问Forms和Template Syntax章节。
<input [(ngModel)]="hero.name" placeholder="name">
浏览器刷新后,我们可以看到修改后的hero,当我们修改hero的name时候,<h2>
标签的内容也会立即随之变动。
回顾历程
让我们盘点一下我们所建立的内容:
- 英雄之旅使用双花括号插值(一种表单单向数据绑定)来展示应用的
title
属性和Hero
对象。 - 我们使用ES2015模板字符串写了一个多行template来使之更可读。
- 我们利用
ngModel
内置指令对<input>
元素进行双向数据绑定,使之可以同时展示和修改hero的name值。 ngModel
指令将变更同时传播到任何绑定了hero.name
的页面元素
运行在线示例查看最终效果。
以下是完整的app.component.ts
文件内容:
import { Component } from '@angular/core';
export class Hero {
id: number;
name: string;
}
@Component({
selector: 'my-app',
template: `
<h1>{{title}}</h1>
<h2>{{hero.name}} details!</h2>
<div><label>id: </label>{{hero.id}}</div>
<div>
<label>name: </label>
<input [(ngModel)]="hero.name" placeholder="name">
</div>
`
})
export class AppComponent {
title = 'Tour of Heroes';
hero: Hero = {
id: 1,
name: 'Windstorm'
};
}