文档章节

AngularDart4.0 英雄之旅-教程-05多组件

scooplol
 scooplol
发布于 2017/11/08 11:30
字数 1849
阅读 62
收藏 0

 

AppComponent正在做所有的事情。 一开始,它展示了一个英雄的细节。 然后,它成为一个英雄和英雄细节列表的主/细节形式。 很快就会有新的要求和能力。 您不能在一个组件之上填充所有功能; 这是不可维护的。

您需要将其分解为子组件,每个子组件都专注于特定的任务或工作流程。 最终,AppComponent可以成为托管这些子组件的简单shell

在这个页面中,您将通过将英雄细节划分为单独的,可重用的组件来迈向这个方向的第一步。 当你完成后,应用程序应该看起来像这样。

从哪里开始

在开始使用本页面之前,请确认您之前在“Tour of Heroes”中拥有以下结构。 如果没有,请返回前面的页面。

如果还没运行,请启动应用,保持应用处于运行状态

创建英雄详情组件

创建文件:hero_detail_component.dart,这个文件将控制新组件HeroDetailComponent

Angular 约定

  • 组件类名称使用驼峰命名法并以“Component”结尾,例:HeroDetailComponent
  • 组件文件的名称使用Snake Case命名法-单词小写且使用下划线分割以_component结束,例:hero_detail_component.dart
  • 内部实现文件应该放在lib / src下。 有关详细信息,请参阅pub package布局约定。

编写HeroDetailComponent文件:lib/src/hero_detail_component.dart (initial version)

import 'package:angular/angular.dart';
import 'package:angular_forms/angular_forms.dart';

@Component(
  selector: 'hero-detail',
  directives: const [CORE_DIRECTIVES, formDirectives],
)
class HeroDetailComponent {
}

创建一个组件,一定要引入主Angular 库。

@Component注解提供组件的Angular元数据。 CSS选择器名称hero-detail将与在父组件的模板中标识该组件的元素标签相匹配。 在本教程页面结尾处,您将向AppComponent模板添加一个<hero-detail>元素。

Hero详情模板

要将英雄细节视图移动到HeroDetailComponent,请从AppComponent模板的底部切割英雄细节内容,并将其粘贴到@Component注解的新模板参数中。

HeroDetailComponent有一个英雄,而不是一个选定的英雄。 在模板中的任何地方用单词“hero”替换“selectedHero”。 完成后,新模板应该如下所示:lib/src/hero_detail_component.dart (template)

template: '''
  <div *ngIf="hero != null">
    <h2>{{hero.name}} details!</h2>
    <div><label>id: </label>{{hero.id}}</div>
    <div>
      <label>name: </label>
      <input [(ngModel)]="hero.name" placeholder="name">
    </div>
  </div>''',

添加英雄属性

HeroDetailComponent模板绑定到组件的英雄属性。 将该属性与必要的导入一起添加到HeroDetailComponent类中。lib/src/hero_detail_component.dart (hero)

import 'hero.dart';

class HeroDetailComponent {
  Hero hero;
}

英雄属性是一个输入属性

在此页面的后面,父AppComponent将通过将其selectedHero绑定到HeroDetailComponenthero属性来通知子HeroDetailComponent显示哪个英雄。 绑定将如下所示:

<hero-detail [hero]="selectedHero"></hero-detail>

在等号(=)左侧的英雄属性周围放置方括号使其成为属性绑定表达式的目标。 您必须将目标绑定属性声明为输入属性。 否则,Angular拒绝绑定并抛出一个错误。

声明这个hero是一个输入属性,用@Input()注释它:lib/src/hero_detail_component.dart (Input annotation)

@Input()
Hero hero;

属性指令页面中了解有关输入属性的更多信息。

hero属性是HeroDetailComponent类中唯一的东西。 它所做的就是通过其hero输入属性接收一个hero对象,然后绑定该属性到模板上。 这是完整的HeroDetailComponent

lib/src/hero_detail_component.dart

import 'package:angular/angular.dart';
import 'package:angular_forms/angular_forms.dart';
import 'hero.dart';
@Component(
  selector: 'hero-detail',
  template: '''
    <div *ngIf="hero != null">
      <h2>{{hero.name}} details!</h2>
      <div><label>id: </label>{{hero.id}}</div>
      <div>
        <label>name: </label>
        <input [(ngModel)]="hero.name" placeholder="name">
      </div>
    </div>''',
  directives: const [CORE_DIRECTIVES, formDirectives],
)
class HeroDetailComponent {
  @Input()
  Hero hero;
}

HeroDetailComponent添加到AppComponent

AppComponent仍然是主/明细视图。 它用于在切出模板部分之前显示英雄细节。 现在它将委托给HeroDetailComponent

首先导入HeroDetailComponent,以便AppComponent可以引用它

import 'src/hero_detail_component.dart';

回想一下,hero-detailHeroDetailComponent元数据中的CSS选择器。 这是代表HeroDetailComponent的元素的标签名称。

AppComponent模板的底部附近添加一个<hero-detail>元素,英雄细节视图。

通过将AppComponentselectedHero属性绑定到HeroDetailComponenthero属性来将主AppComponentHeroDetailComponent进行协调。

<hero-detail [hero]="selectedHero"></hero-detail>

现在每当selectedHero改变时,HeroDetailComponent就会得到一个新的hero显示。

修改后的AppComponent模板应该如下所示:lib/app_component.html

<h1>{{title}}</h1>
<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes"
      [class.selected]="hero === selectedHero"
      (click)="onSelect(hero)">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>
<hero-detail [hero]="selectedHero"></hero-detail>

每次用户选择一个新的英雄时,细节应该更新。 这还没有发生! 点击一个英雄。 没有细节。 如果您在浏览器开发工具的控制台中查找错误。 没有错误。

就好像Angular忽略了新的标签。 那是因为它忽略了新的标签。

指令列表

浏览器会忽略不能识别的HTML标签和属性。 Angular也是如此。

你已经导入了HeroDetailComponent,并且你已经在模板中使用了<hero-detail>,但是你还没有将它告诉给Angular。

就像您为内建的Angular指令所做的那样,通过将其列在元数据指令列表中,告诉Angular关于英雄详细信息组件。 你不需要formDirectives,所以删除它,并在文件顶部的angular_forms导入:lib/app_component.dart (directives)

directives: const [CORE_DIRECTIVES, HeroDetailComponent],

刷新浏览器。 该应用程序工作!

应用程序设计更改

和以前一样,每当用户点击一个英雄名字时,英雄详情就会出现在英雄列表的下方。 但是现在HeroDetailComponent正在呈现这些细节。

将原始AppComponent重构为两个组件,现在和将来都会带来好处:

  1. 您通过减少其职责简化了AppComponent
  2. 您可以将HeroDetailComponent演变成一个丰富的英雄编辑器,而无需触摸父AppComponent
  3. 你可以在不触及英雄详情视图的情况下演化AppComponent
  4. 您可以在将来的某个父组件的模板中重用HeroDetailComponent

查看应用程序结构

确认您具有以下结构:

这里是本页讨论的代码文件

lib/src/hero_detail_component.dart

import 'package:angular/angular.dart';
import 'package:angular_forms/angular_forms.dart';
import 'hero.dart';
@Component(
  selector: 'hero-detail',
  template: '''
    <div *ngIf="hero != null">
      <h2>{{hero.name}} details!</h2>
      <div><label>id: </label>{{hero.id}}</div>
      <div>
        <label>name: </label>
        <input [(ngModel)]="hero.name" placeholder="name">
      </div>
    </div>''',
  directives: const [CORE_DIRECTIVES, formDirectives],
)
class HeroDetailComponent {
  @Input()
  Hero hero;
}

lib/app_component.dart 

import 'package:angular/angular.dart';
import 'src/hero.dart';
import 'src/hero_detail_component.dart';
import 'src/mock_heroes.dart';
@Component(
  selector: 'my-app',
  templateUrl: 'app_component.html',
  styleUrls: const ['app_component.css'],
  directives: const [CORE_DIRECTIVES, HeroDetailComponent],
)
class AppComponent {
  final title = 'Tour of Heroes';
  List<Hero> heroes = mockHeroes;
  Hero selectedHero;
  void onSelect(Hero hero) => selectedHero = hero;
}

lib/app_component.html

<h1>{{title}}</h1>
<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes"
      [class.selected]="hero === selectedHero"
      (click)="onSelect(hero)">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>
<hero-detail [hero]="selectedHero"></hero-detail>

你走过的路


以下是您在此页面中所取得的成果:

  • 您创建了一个可重用的组件。
  • 您学习了如何使组件接受输入。
  • 您学会了在 directives列表中声明应用程序指令。
  • 您学会了将父组件绑定到子组件。

你的应用应该看起来像这个实例(查看源代码)。

前方的路

“The Tour of Heroes ”游戏的应用程序可以更多地使用共享组件,但其(模拟)数据仍然是在AppComponent中硬编码的。 这是不可持续的。 数据访问应重构为单独的服务,并在需要数据的组件之间共享。

您将学习在下一个教程页面中创建服务。

下一节

© 著作权归作者所有

scooplol
粉丝 17
博文 103
码字总数 205785
作品 0
南充
程序员
私信 提问
AngularDart4.0 英雄之旅-教程-04明细

在此页面中,您将扩展“Tour of Heroes”应用程序,以显示英雄列表,并允许用户选择英雄并显示英雄的详细信息。 完成此页面后,该应用应该看起来像这个实例(查看源代码)。 必备条件 在继续...

scooplol
2017/10/24
68
0
AngularDart4.0 英雄之旅-教程-03英雄编辑器

码云项目页:https://gitee.com/scooplolwiki/toh-1 在这一部分,您将修改起始应用程序以显示有关英雄的信息。 然后,您将添加编辑英雄信息的功能。 完成后,应用程序应该看起来像这个实例(...

scooplol
2017/10/22
85
0
AngularDart4.0 英雄之旅-教程-02启动应用

码云项目页:https://gitee.com/scooplolwiki/toh-0 此教程讲解Angular的文件架构,(查看源代码)查看应用程序。 创建应用 开始,创建名为angulartourof_heroes的项目,使用WebStorm或者命令...

scooplol
2017/10/19
164
11
dota玩家与英雄契合度的计算器,python语言scrapy爬虫的使用

首发:个人博客,更新&纠错&回复 演示地址在这里,代码在这里。 一个dota玩家与英雄契合度的计算器(查看效果),包括两部分代码: 1.python的scrapy爬虫,总体思路是page->model->result,从...

祁达方
2015/12/01
105
0
Unity网络多玩家游戏开发教程第1章Unity自带网络功能

Unity网络多玩家游戏开发教程第1章Unity自带网络功能 Unity拥有大量的第三方插件,专门提供了对网络功能的支持。但是,大部分开发者第一次接触到的还是Unity自带的网络功能,也就是大家经常说...

大学霸
2014/10/30
1K
1

没有更多内容

加载失败,请刷新页面

加载更多

程序设计基础(C)第06讲例程

1summing.c /* summing.c -- 根据用户键入的整数求和 */#include <stdio.h>int main(void){ long num; long sum = 0L; /* 把sum 初始化为0 */ int status; p......

树人大学数字媒体吴凡
24分钟前
6
0
聊聊nacos config的publishConfig

序 本文主要研究一下nacos config的publishConfig ConfigController nacos-1.1.3/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java @Controller@R......

go4it
52分钟前
5
0
Eureka应用注册与集群数据同步源码解析

在之前的EurekaClient自动装配及启动流程解析一文中我们提到过,在构造DiscoveryClient类时,会把自身注册到服务端,本文就来分析一下这个注册流程 客户端发起注册 boolean register() t...

Java学习录
今天
11
0
Java描述设计模式(15):责任链模式

本文源码:GitHub·点这里 || GitEE·点这里 一、生活场景描述 1、请假审批流程 公司常见的请假审批流程:请假天数 当 day<=3 天,项目经理审批当 3<day<=5 天,部门经理审批当 day>5 天...

知了一笑
今天
10
0
总结:数组与链表

1、内存申请:数组在内存上是连续的空间;链表,内存地址上可以是不连续的。 2、查询速度:数组可以随机访问,链表必须顺序访问,即从首个元素开始遍历,逐个查找,所以数组查询很快。 3、写入...

浮躁的码农
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部