在本系列的上一篇文章中,我们在todo-web-app项目中为页面整体的布局(layout)开发了可重用的组件: header和footer(footer是作为课后作业让大家完成的),在本文中,我们将带大家继续深入Angular中的组件,构造一个用于显示业务数据的组件。
我们的实验案例是构造一个管理个人待办事项的应用(todo)。之所以选择这个案例的,是因为这个案例业务上足够简单,大多数人都能理解,这样就不需要在理解业务规则上花太多的时间。当然,我们的案例的Todo是一个比正式应用还要简化的场景,所以无论是数据结构还是算法都更简单。
在开始前,确保你已经进入我们案例项目的更目录: PROJECT_ROOT, 在我的电脑上这个目录是: d:\todo-web-app
建立业务实体类
首先我们建立一个实体类: Todo, 用来表示一个待办事项的实体(数据),在命令行执行以下命令:
1 2 3
| D:\todo-web-app>ng g class models\Todo CREATE src/app/models/todo.spec.ts (146 bytes) CREATE src/app/models/todo.ts (22 bytes)
|
执行完成后,项目的目录应该是这样的:
1 2 3 4 5 6 7 8 9 10 11 12
| todo-web-app + src + app + components + layout header.component.css header.component.html header.component.spec.ts header.component.ts + models + todo.ts + todo.spec.ts
|
我们可以看到在src/app/models目录中多了todo.ts这个文件,打开这个文件,添加如下的属性定义在类的定义中:
1 2 3 4 5 6 7
| export class Todo { id: number; title: string; desc: string; done: boolean; }
|
构建可重用的卡片组件
为了在页面上显示待办事项的细节信息,我们选择以卡片的方式来展示每一个待办事项。又因为我们不希望卡片和待办事项的业务紧密依赖,影响了卡片组件的复用,因此我们决定使用来构建卡片组件,具体原理可以参考:用ng-content使Angular中的自定义组件更灵活(一) 和 用ng-content使Angular中的自定义组件更灵活(二) 这两篇文章。下面我们描述实验过程:
在命令行执行以下命令构建卡片组件:
1 2 3 4 5 6
| D:\todo-web-app>ng g component components\widget\Card CREATE src/app/components/widget/card/card.component.html (23 bytes) CREATE src/app/components/widget/card/card.component.spec.ts (614 bytes) CREATE src/app/components/widget/card/card.component.ts (261 bytes) CREATE src/app/components/widget/card/card.component.css (0 bytes) UPDATE src/app/app.module.ts (585 bytes)
|
执行完成后,项目的目录应该是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| todo-web-app + src + app + components + layout header.component.css header.component.html header.component.spec.ts header.component.ts + widget card.component.css card.component.html card.component.spec.ts card.component.ts + models + todo.ts + todo.spec.ts
|
修改组件类定义文件: card.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { Component, OnInit, Input } from '@angular/core';
@Component({ selector: 'app-card', templateUrl: './card.component.html', styleUrls: ['./card.component.css'] }) export class CardComponent implements OnInit {
@Input() title: string;
constructor() { }
ngOnInit() { }
}
|
在这个文件中,我们只是简单的加入了一个title的属性,因为这个属性是和具体的Todo业务无关的,可以理解为任何卡片都需要一个title。 并且我们将该属性修饰为Input, 标明它是要给输入参数,原理参考: 用@Input装饰器为Angular中的组件传值
接下来,更改组件的显示文件: card.component.html, 首先,删除所有自动生成的内容,然后添加以下内容:
1 2 3 4 5 6 7 8 9 10 11
| <div class="card"> <div class="card-header"> {{ title }} </div> <div class="card-content"> <ng-content select=".card-content"></ng-content> </div> <div class="card-footer"> <ng-content select=".card-footer-toolbar"></ng-content> </div> </div>
|
在显示界面中,我们用绑定了title这个属性,并用ng-conent建立了两个可替换内容的区域。关于可替换的原理,请参考: 用ng-content使Angular中的自定义组件更灵活(一) 和 用ng-content使Angular中的自定义组件更灵活(二) 这两篇文章
最后,为了能够看到效果,我们为卡片组件加上一些CSS, 修改 card.component.css 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| .card { margin: 10px 10px; border: 1px solid #000000; } .card-header { border: 1px solid #119900; background: #119900; } .card-content { background: #e7e7f0; } .card-footer { background: #880011; }
|
在本文中,CSS主要是要突出效果,以在界面上区分出组件,所以暂时不考虑美观的问题(我们将在后面的文章中来美化)
使用组件
首先,我们在程序入口的app组件中,加入模拟的待办事项数据,修改 apop.component.ts 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import { Component } from '@angular/core';
import { Todo } from './models/todo';
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'todo-web-app';
tasks: Todo[] = [ { "id": 1, "title": "task1", "desc": "desc1", "done": false }, { "id": 2, "title": "task2", "desc": "desc2", "done": false } ] }
|
可以看到,我们在代码中引入了实体类Todo, 然后声明了一个todo的数组tasks。
然后修改组件显示文件: app.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <app-header title="Angular课程"></app-header> <div> <div *ngFor="let task of tasks"> <app-card [title]="task.title"> <div class='card-content'> <div>{{ task.desc }} </div> <div>{{ task.done }} </div> </div> <div class="card-footer-toolbar"> <button>Done</button> </div> </app-card> </div> </div>
|
可以看到,我们在html中使用了刚才定义好的card组件(app-card), 用它来显示待办事项。
观看效果
修改完以后,我们执行ng serve运行程序,然后在浏览器中观看效果。如果一切正确,应该可以看到如下界面显示
下一步
在 下一篇文章中,我们将带大家实验界面操作并初步引入服务的概念(Service)。