顶层概念
Angular应用其实就是一棵由组件构成的树,游览器启动时会引导(bootstrap)最顶层的组件,然后递归渲染下级组件。
每个组件由三个部分组成:
- 组件注解
- 视图
- 控制器
组件注解
@Component注解是对组件进行配置的地方,包括selector、template、style。
输入/输出绑定
方括号[]用来传递输入,圆括号()用来处理输出。
<products-list [productList]="products"></product-list>
左边的[productList]是指,我们希望在product-list组件中设置名为productList的输入。右边的“products”是指,我们希望将输入设置为 products表达式 的值。
(onProductSelected)="productWasSelected($event)"
(onProductSelected)是我们要监听的输出的名称,”productWasSelected($event)”是当有新的输入(监听事件被触发)时我们想要调用的方法,$event在这里是一个特殊的变量,用来表示输出的内容。
组件的输入
组件的输入有两种指定方式:
- @Component里面配置,如:
@component({selector: 'ss',inputs: ['name'],outputs: ['xxx'],template: ...})
- @Input注解。如:
@Input() name: string;
假如希望标签元素的属性和组件实例中的属性使用不同的名称(尽量避免这种方式),有一下格式:
inputs输入字符串列表中可以使用 'componentProperty: exposedProperty' //'组件实例属性:标签元素属性'
@Inputs注解中:@Input('exposedProperty') componentProperty: type;
触发自定义事件
- 在@Component配置中,指定outputs配置项(公开事件)
- 在实例属性中,设置一个EventEmitter(事件触发器)
- 在适当的时候,通过EventEmitter触发事件
EventEmitter是一个实现观察者模式的对象,它是管理一系列订阅者并向其发布事件的对象。当我们把一个EventEmitter赋值给一个输出的时候,Angular会自动帮我们订阅事件而不需要我们自己订阅(也可以自己实现订阅逻辑)
Host配置项
host配置项可以在组件内部配置宿主元素,指的是实现了该host配置的component
关于一点注意
<img src="{{ product.imageUrl }}">
<img [src]="product.imageUrl">
两个式子中前一个是错的,为什么?因为如果浏览器在angular运行起来之前就加载了这段模板,就会尝试以字符串{{ product.imageUrl }}为url来加载图片;而通过[src]元素属性,我们告诉angular我们希望使用img标签的[src]输入。一旦表达式的值解析完成,Angular就会把src元素属性替换为表达式的值。
关于数据架构
目前不是很了解
一些内置指令
ngIf
ngSwitch
<ul [ngSwitch]="choice">
<li *ngSwitchCase="1">First choice</li>
<li *ngSwitchDefault>Default choice</li>
</ul>
ngStyle
[style.<cssProperty>]="value"
[ngStyle]="{color: 'while','background-color': 'blue'}"
[style.font-size.px]="12"
ngClass
[ngClass]="{bordered: true}"
[ngClass]="['blue','round']"
ngFor
*ngFor="let item of items; let idx = index"
ngNonBindable
当我们不想要angular编译或者绑定页面中的某个特殊部分时可以使用该指令。
Angular中的表单
两个最基础的表单对象:
FormControl: 代表一个输入字段,封装了字段的值和状态,比如是否有效、是否脏(被修改过)、是否有误等。
FormGroup: 为一组FormControl提供总包接口(wrapper interface),可以理解为其中包含了很多个FormControl。当我们试图从FormControl中获取value时,会收到一个“键值对”结构的对象。能一次性获取全部FormControl的值而无需逐一遍历。
查阅官方表单库
FormsModule
ReactiveFormsModule
当我们导入FormsModule的时候,NgForm会自动附加到任何能匹配到其selector的节点上(如:form标签)
NgForm的selector是:
form:not([ngNoForm]):not([formGroup]),ngForm,[ngForm]
NgForm为我们提供了两个重要的功能:
- 一个名叫ngForm的FormGroup对象
- 一个输出事件(ngSubmit)
NgModel
NgModel指令的selector是ngModel。当使用不带属性值的ngModel时,我们是要指定:
<input type="text" name="sku" ngModel>
NgModel会创建一个新的FormControl对象,把它自动添加到父FormGroup上,并把这个FormControl对象绑定到一个DOM上。也就是说,它会在视图中的input标签和FormControl对象之间建立关联。这种关联是通过name属性建立的。
当我们给ngModel同时使用上[] 和 () 时,表示双向绑定。
<input ... [formControl]="myForm.get('productName')" [(ngModel)]="productName">
这里ngModel只负责将input绑定到对象实例上,与FormControl的功能是互相独立的。
FormBuilder
使用ngForm和ngModel隐式构建FormControl和FormGroup无法为我们提供更多定制化选项。而FormBuilder构建表单更加灵活和通用。
一般步骤如下:
- 在组件定义类中通过依赖注入FormBuilder,创建FormGroup对象。
- 在视图表单中使用自定义的FormGroup。
代码示例:
export class DemoFormBuilder{
myForm: FormGroup;
constructor(bf: FormBuilder){
this.myForm = fb.group({
'sku': ['ABC123']; //设置一个名为sku的FormControl,其默认值为"ABC123"
});
}
}
这里涉及了FormBuilder两个主要函数:
- control:用于创建一个新的FormControl
- group: 用于创建一个新的FormGroup
在视图中使用myForm
<form [formGroup]="myForm"> // 用myForm作为这个表单的FormGroup
<input ... [formContorl]="myForm.controls['sku']"> //将FormControl绑定到input标签上
添加表单验证
- 为FormControl对象指定验证器
- 在视图中检查验证器的状态,并据此采取行动
要为FormControl对象分配一个验证器,我们可以直接把它作为第二个参数传给FormControl的构造函数
let control = new FormControl('sku',Validators.required);
也可以使用FormBuilder
export class DemoFormBuilder{
myForm: FormGroup;
constructor(bf: FormBuilder){
this.myForm = fb.group({
'sku': ['',Validators.required];
});
}
}
视图中验证
通过myForm.valid 或者 sku.valid 来检查有效性;
特定验证:myForm.hasError(‘required’,‘sku’) 检查form里面特定字段是否有某种错误
自定义验证器
Validators.required源码
export class Validators{
static required(c: FormControl): StringMap<string,boolean>{
return isBlank(c.value) || c.value == "" ? {"required": true} : null;
}
}
类似的,一个验证器:
另外,当给一个FormControl添加两个以上验证器的时候,可以使用 Validators.compose() 来包装起来。
监听变化
FormControl和FormGroup都带有EventEmitter(事件发射器),可以通过它来观察变化。如通过调用control.valueChanged访问这个EventEmitter,然后使用subscribe方法添加一个监听器。
this.form.valueChanged.subscribe(
(form: any) => {
console.log('form changed to: ',form);
}
);
我们传递了一个带有next键的对象,next键是我们希望当值发生变化的时候被调用的函数
next键是什么???