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从组件读取titlehero属性并展示它们。这就是“插值”形式的单向数据绑定。

想要学习更多关于插值的信息,请访问Displaying Data 章节

Hero对象

此时,我们的hero仅仅是个名称,但是它需要更多的属性。让我们把hero从一个字符串转化成一个类。

创建一个带有idname属性的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的idname属性各添加一个<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的只是,请访问FormsTemplate 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'
  };
}

results matching ""

    No results matching ""