Dart和Angular2的英雄之旅(2):英雄编辑器

很久很久以前

每个故事都有一个起点,而我们的故事则开始于“快速入门”的结尾处。

创建名为 angular2_tour_of_heroes 的文件夹,并且遵循快速入门的步骤初始化它——搭建环境、目录结构,并放入《英雄之旅》的核心文件。我们应该有如下目录结构:

运行这部分的在线实例
你也可以下载源码作为起步

保持应用的编译和运行

我们需要启动Dart编译器,它会监视文件变更,并且启动服务器。我们只要敲入:

pub serve

这个命令会在监视模式(watch mode)下运行编译器,启动服务器,并在我们构建《英雄之旅》的时候让应用得以持续运行。

显示我们的英雄

我们想在应用中显示英雄数据。

让我们来为 AppComponent 添加两个属性: title 属性表示应用的名字,而 hero 属性表示一个名叫“ Windstorm ”的英雄。

class AppComponent {
  String title = 'Tour of Heroes';
  var hero = 'Windstorm';
}

现在,我们为这些新属性建立数据绑定,以更新 @Component 注释的模板。

template: '<h1>{{title}}</h1><h2>{{hero}} details!</h2>'

刷新浏览器,显示我们的标题和英雄。

这里的“双大括号”会告诉应用:从组件中读取 titlehero 属性,并且渲染它们。这就是单向数据绑定的“插值表达式”形式。

注:要了解插值表达式的更多知识,参阅 “显示数据”一章 。

Hero对象

此时此刻,我们的英雄还只有一个名字。显然,它应该有更多属性。让我们把hero从一个字符串字面量转换成一个类。

创建一个 Hero 类,它具有 id name 属性。现在,把下列代码放在 app_component.dart 的顶部附近。

class Hero {
  final int id;
  String name;

  Hero(this.id, this.name);
}

现在,我们有了一个 Hero 类,让我们重构组件的 hero 属性为 Hero 类型。 然后以1为id、以“Windstorm”为名字,初始化它。

Hero hero = new Hero(1, 'Windstorm');

因为我们把hero从一个字符串换成了对象,所以也得更新模板中的绑定表达式,来引用hero的name属性。

template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2>'

刷新浏览器,并继续显示这位英雄的名字。

添加更多的HTML

能显示名字虽然不错,但我们还想看到这位英雄的所有属性。我们将添加一个 <div> 来显示英雄的 id 属性,用另一个 <div> 来显示英雄的 name 属性。

template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2><div><label>id: </label>{{hero.id}}</div><div><label>name: </label>{{hero.name}}</div>'

哦!模板字符串越来越长了。我们最好注意点,避免在模板中出现拼写错误。

多行模板字符串

我们可以通过连接字符串制作更加可读的模板,但这样仍然太难看了——难于阅读,容易拼错。取而代之,让我们利用Dart中模板字符串的特性,来让代码保持清晰。

把模板的双引号改成三个引号,并且让 <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>'''

编辑我们的英雄

我们希望能在一个文本框中编辑英雄的名字。

把英雄的名字从单纯的 <label> 重构成 <label><input> 元素的组合,就像下面这样:

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

在浏览器中,我们看到英雄的名字已经出现在 <input> 文本框中。但感觉有点不妥。当修改名字时,我们的改动并没有反映到 <h2> 中。使用单向数据绑定,我们没法实现所期望的这种行为。

双向绑定

我们计划在 <input> 中显示英雄的名字,修改它,并且能看到——绑定英雄名字的地方的——所有修改。简而言之,我们需要双向数据绑定。

让我们更新模板,使用内置指令 ngModel 来进行双向绑定。

注:要了解更多 ngModel 的内容,参阅 “表单(Form)”和“模板语法(Template Syntax)”章节。

用下面的HTML替换 <input> 标签:

<input [(ngModel)]="hero.name" placeholder="name">

刷新浏览器。又见到我们的英雄了。我们可以编辑英雄的名字,并看到这个改动立刻体现在 <h2> 中。

我们已经走过的路

我们来盘点一下已经构建的内容。

  • 我们的《英雄之旅》使用双大括号 (插值表达式,单向数据绑定的一种形式 ) 来显示应用的标题和 Hero 对象的属性。
  • 我们使用Dart模板字符串写了一个多行模板,让我们的模板更有可读性。
  • 在使用了内置的 ngModel 指令为 <input> 元素添加双向数据绑定后,我们可以同时显示和修改英雄的名字。
  • 数据变化后, ngModel 指令还影响到了每一个对 hero.name 的其它绑定。

完整的 app_component.dart 内容如下:

import 'package:angular2/core.dart';

class Hero {
  final int id;
  String name;
  Hero(this.id, this.name);
}
@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>'''
)
class AppComponent {
  String title = 'Tour of Heroes';
  Hero hero = new Hero(1, 'Windstorm');
}

前方的路

我们的《英雄之旅》只显示了一个英雄,而我们真正要显示的是一个英雄列表。我们还希望允许用户选择一个英雄,并且显示它的详细信息。我们还将学习更多:获取一个列表、把它们绑定到模板,并允许用户选择它。这些都在 教程的下一章

本文出自“Dart语言中文社区”,允许转载,转载时请务必以超链接形式标明文章原始出处
本文地址:
http://www.cndartlang.com/807.html

发表评论

登录后才能评论