How Angular Works
这部分注重给一个全面而基础的部分。最重要点就是Angular是由组件组成。
Application
应用是最终形态,它是由一连串的组件组成树形结构。
在结构根部,最高级别组件就是应用自己,也就是浏览器启动这个app的地方。
组件的一个重要特性就是可以组成,就是可以通过一个个小组件组成一个大组件。
因为是树形结构,所以由父组件,子组件组成。父组件逐层渲染子组件。
如下是一个例子,把它分成组件。
可首先分为3层,
1. 导航栏
2. 面包屑
3. 产品列表
其中产品列表是一系列产品集合,多个产品行,multiple Product Rows
每一行,由产品图片,产品信息分类,价格组成
最终集合到一起
这一章节主要解释
- 如何把应用拆解成组件
- 如何用
input
重复利用组件 - 如何处理用户交互,比如组件上的
click
产品模型
Angular的一个重要特点就是不提供一个具体的模型库。它灵活的支持各类模型和数据结构。
用户需要决定如何搭建和使用。
如下, 建造一个product
模型,接受5个参数
用public
声明表示这是全局变量
export class Product {
constructor(
public sku: string,
public name: string,
public imageUrl: string,
public department: string[],
public price: number) {
}
}
之前提到过,Anjular应用是由组件搭建而成。而应用本身就是最高级别组件。
每一个组件有3部分组成
- Component Decorator
- View
- Controller
一个基本top-level AppComponent 如下
@Component({
selector: 'inventory-app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
@Component
就是 Decorator,它的装饰器包括:
- selector
: 告诉Angular匹配那一个元素
- templateUrl
:定义view
controller
是由对应的class
定义
组件装饰器 Component Decorator
@Component
装饰器负责配置组件。
selector
设置模版的tag
,用于HTML引用。
定义HTML的哪些元素匹配这个component。
比如selector: 'inventory-app-root',
就是告诉HTML有如下tag
<inventory-app-root></inventory-app-root>
HTML也可以这么引用:
<div inventory-app-root></div>
template
定义HTML页面
可以在template直接输入
或者引用
add data and view
模型已建好,需要添加一条数据,
可以在component里引入模型添加数据 p90
一条数据直接(), 多条用数组[]
import { Product } from './product.model';
class AppComponent {
product: Product[];
constructor() {
this.product = new Product[
new Product(
'MYSHOES',
'Black Running Shoes',
'/assets/images/products/black-shoes.jpg',
['Men', 'Shoes', 'Running Shoes'],
109.99),
new Product(
...
]
}
}
在HTML页面引入数据
<h1>{{ product.name }}</h1>
<span>{{ product.sku }}</span>
click it
做一个选择按钮,
先在component定义函数
productWasSelected(product: Product): void {
console.log('Product clicked: ', product);
}
product list component
计划创建produce-list
组件用来显示produce list
但是在之前,现在appcomponent组件下定义:
<div class="inventory-app">
<products-list
[productList]="products" //input
(onProductSelected)="productWasSelected($event)"> //outut
</products-list>
</div>
组件之间数据绑定
在Angular中
[]处理input
子组件接收数据
父组件通过[]来把数据传到子组件
在本例中
[productList]="products"
左边 [productList]表示用productList
来作为produce-list
组件的输入
右边“products”要传输的目标对象,也就是AppComponent组件的this.products
.
如何知道productList是produce-list组件的输入名?
在组件的文档中定义,input和output会作为类似于public API被定义。
()处理output
子组件发送数据
本例中
(onProductSelected)="productWasSelected($event)">
监听组件的onProductSelected
,
右边productWasSelected
表示output接收数据时,触发的函数,来自AppComponent组件
$event 表示传输的变量/变量
再创建produce-list
组件 p98
再组件定义
...
export class ProductsListComponent {
@Input() productList: Product[];
@Output() onProductSelected: EventEmitter<Product>;
通过 ProductsListComponent
的input传递this.products
(AppComponent)
在product-list组件 导入模型
并设置
...
export class ProductsListComponent {
@Input() productList: Product[];
...
在product-list组件的html里
<div
*ngFor="let myProduct of productList"
[product]="myProduct"> //[product]来自于product-row组件
</div>
Output的输出语法是 (output)=”action”
一个output需要3个部分
1, 在组件定义output
2, 配置一个事件触发器EventEmitter
3,从事件触发器里正确的触发事件
EventEmitter是时间触发器,一个对象用来执行观察模式,用来
1. 保持订阅列表
2. 发表事件
比如
letee=newEventEmitter();
ee.subscribe((name:string)=>console.log(`Hello${name}`));
ee.emit("Nate");
// "Hello Nate"
时间触发器的使用p102 p125
HostBinding
p110, p133
宿主绑定,继承父组件的元素设置
设置ProductRowComponent组件
分为3个子组件
在image组件中,导入img
, p111, p134
设置模版
<img class="product-image" [src]="product.imageUrl">
或者
<img src="{{ product.imageUrl }}">
设置产品分类面包屑
<span *ngFor="let name of product.department; let i=index">
<a href="#">{{ name }}</a>
<span>{{i < (product.department.length-1) ? '>' : ''}}</span>
</span>
如下
Women > Apparel > Jackets & Vests
app启动程序
ng serve -> .angular-cli.json -> main.ts -> AppModule -> ….