显示数据

作者: soojade | 来源:发表于2016-12-16 16:05 被阅读23次

    版本:Angular 5.0.0-alpha

    在 Angular 中最典型的数据显示方式,就是把 HTML 模板中的控件绑定到 Angular 组件的属性。

    本章,你将创建一个英雄列表组件。显示英雄名字的列表,并根据条件在列表下方显示一条消息。

    最终的用户界面是这样的:


    在线示例(查看源码)演示了本章描述的所有语法和代码片段。

    使用插值表达式显示组件属性

    要显示组件的属性,最简单的方式就是通过插值表达式 (interpolation) 来绑定属性名。 要使用插值表达式,就把属性名包裹在双花括号里放进视图模板,如{{myHero}}

    按照配置开发环境的说明,创建一个名为displaying_data的新项目。

    然后,到app_component.dart文件,修改组件的模板和代码。

    修改完之后,应该是这样的:

    // lib/app_component.dart
    
    import 'package:angular/angular.dart';
    @Component(
      selector: 'my-app',
      template: '''
        <h1>{{title}}</h1>
        <h2>My favorite hero is: {{myHero}}</h2>
      ''',
    )
    class AppComponent {
      final title = 'Tour of Heroes';
      String myHero = 'Windstorm';
    }
    

    再把两个属性titlemyHero添加到之前空白的组件中。
    修改完的模板会使用双花括号形式的插值表达式来显示这两个模板属性:

    template: '''
      <h1>{{title}}</h1>
      <h2>My favorite hero is: {{myHero}}</h2>
    ''',
    

    Angular 自动从组件中提取titlemyHero属性的值,并且把这些值插入浏览器中。当这些属性发生变化时,Angular 就会自动更新显示。

    严格来说,“重新显示”是在某些与视图有关的异步事件之后发生的,例如,按键、定时器完成或对 HTTP 请求的响应。

    注意,我们没有调用 new 来创建AppComponent类的实例,是 Angular 替我们创建了它。那么它是如何创建的呢?

    @Component注解中的 CSS 选择器 selector,指定一个名为<my-app>的元素。该元素是index.htmlbody 里的占位符。

    // web/index.html(body)
    
    <body>
      <my-app>Loading...</my-app>
    </body>
    

    当你通过AppComponent类(在web/main.ts中)启动应用时,Angular 在index.html中查找一个<my-app>元素,找到它,然后实例化一个AppComponent的实例,并将其渲染到<my-app>标签中。

    现在运行应用。它应该显示出标题和英雄名:

    内联 (inline) 模板还是模板文件?

    我们可以在两种地方存放组件模板。使用template属性把它定义为内联的,或者把模板定义在一个独立的 HTML 文件中,再通过@Component注解中的templateUrl属性,把它链接到组件元数据。

    到底选择内联 HTML 还是独立 HTML 取决于个人喜好、具体状况和组织策略。上面的应用选择内联 HTML,是因为模板很小,而且没有额外的 HTML 文件显得这个演示简单些。

    无论用哪种风格,模板数据绑定在访问组件属性方面都是完全一样的。

    使用 *ngFor显示一列属性

    要显示一列英雄,先向组件中添加一个包含英雄名字的列表,然后把myHero重新定义为列表中的第一个名字。

    // lib/app_component.dart (class)
    
    class AppComponent {
      final title = 'Tour of Heroes';
      List<String> heroes = [
        'Windstorm',
        'Bombasto',
        'Magneta',
        'Tornado',
      ];
      String get myHero => heroes.first;
    }
    

    现在,在模板中使用 Angular 的ngFor指令来显示heroes列表中的每一项。

    template: '''
      <h1>{{title}}</h1>
      <h2>My favorite hero is: {{myHero}}</h2>
      <p>Heroes:</p>
      <ul>
        <li *ngFor="let hero of heroes">
          {{ hero }}
        </li>
      </ul>
    ''',
    directives: const [CORE_DIRECTIVES] // 使用ngFor 一定要声明指令
    

    这个界面使用了由 <ul><li> 标签组成的无序列表。<li> 元素里的*ngFor是 Angular 的“重复”指令。它将<li>元素(及其子元素)标记为“重复模板”:

    <li *ngFor="let hero of heroes">
      {{ hero }}
    </li>
    

    不要忘记 *ngFor 中的前导星号 (*)。它是语法中不可或缺的一部分。更多信息,见模板语法

    注意看ngFor双引号表达式中的hero,它是一个模板输入变量。 更多模板输入变量的信息,见模板语法中的微语法

    Angular 为列表中的每个条目复制一个<li>元素,在每个迭代中,把hero变量设置为当前条目(英雄)。Angular 把hero变量作为双花括号插值表达式的上下文。

    本例中,ngFor用于显示一个列表,但ngFor可以为任意
    Iterable 对象重复条目。

    @Component(directives: …)

    在模板中使用任何 Angular 指令之前,需要在组件的@Component 注解的directives列表中声明它们。可以单独的列出指令,或者为了方便起见使用 CORE_DIRECTIVES

    // lib/app_component.dart (directives)
    
    import 'package:angular/angular.dart';
    
    @Component(
      selector: 'my-app',
      // ···
      directives: [coreDirectives],
    )
    

    刷新浏览器。现在,英雄们出现在了一个无序列表中。


    为数据创建一个类

    应用代码直接在组件内部直接定义了数据。作为演示还可以,但它显然不是最佳实践。

    现在使用的是到一个字符串列表的绑定。在真实的应用中,大多数是绑定到一个专门的对象。

    要将此绑定转换成使用专门的对象,需要把这个英雄名字的列表变成Hero对象的列表。因此,你需要一个Hero类。

    lib目录创建一个名为hero.dart的新文件,内容如下:

    // lib/src/hero.dart
    
    class Hero {
      final int id;
      String name;
      Hero(this.id, this.name);
      @override
      String toString() => '$id: $name';
    }
    

    你定义了一个包含一个构造函数,两个属性(idname)和一个toString()方法的类。

    使用 Hero 类

    导入了Hero类之后,AppComponent.heroes属性就可以返回一个Hero对象类型的列表了。

    // lib/app_component.dart
    
    List<Hero> heroes = [
      new Hero(1, 'Windstorm'),
      new Hero(13, 'Bombasto'),
      new Hero(15, 'Magneta'),
      new Hero(20, 'Tornado')
    ];
    Hero get myHero => heroes.first;
    

    接下来,修改模板。现在它显示的是英雄的idname。修复它,只显示英雄的name属性。

    // lib/app_component.dart (template)
    
    template: '''
      <h1>{{title}}</h1>
      <h2>My favorite hero is: {{myHero.name}}</h2>
      <p>Heroes:</p>
      <ul>
        <li *ngFor="let hero of heroes">
          {{ hero.name }}
        </li>
      </ul>
    ''',
    

    显示上还和以前一样,不过代码更清晰了。

    通过 NgIf 进行条件显示

    有时,应用需要只在特定情况下显示视图或视图的一部分。

    让我们来修改这个例子,如果多于三位英雄,显示一条消息。

    Angular 的ngIf指令会根据一个布尔条件,插入或移除元素。通过把下面的段落添加到模板的底部,我们可以看到实际效果。

    // lib/app_component.dart (message)
    
    <p *ngIf="heroes.length > 3">There are many heroes!</p>
    

    不要忘了*ngIf中的前导星号 (*)。它是本语法中不可或缺的一部分。 更多ngIf*的内容,见模板语法ngIf 部分。

    双引号中的模板表达式,*ngIf ="heros.length > 3",看起来就像是 Dart。当组件中的英雄列表有三个以上时,Angular 把这个段落添加到 DOM 中,于是消息显示了出来。如果有3个或少于3个,Angular 会忽略这个段落,所以就没有信息显示。更多信息,见模板语法中的模板表达式部分。

    Angular 并不是在显示和隐藏这条消息,它是在从 DOM 中添加和移除这个段落元素。这会提高性能,特别是在一些大的项目中有条件地包含或排除一大堆带着很多数据绑定的 HTML 时。

    试一下。因为列表中有四个条目,所以消息显示了出来。回到app_component.dart,从英雄列表中删除或注释掉一个元素。浏览器刷新后,信息应该不存在了。

    总结

    现在你学会了如何使用:

    • 带有双花括号的插值表达式来显示一个组件属性。
    • ngFor 来显示一列条目。
    • 用一个 Dart 类来为组件描述模型数据并显示模型的属性。
    • ngIf 来根据一个布尔表达式有条件的显示一段HTML。

    下一步

    用户输入

    相关文章

      网友评论

        本文标题:显示数据

        本文链接:https://www.haomeiwen.com/subject/xhwnmttx.html