Angular : 响应式编程, 组件间通信, 表单

Angular 响应式编程相关

-------------------------------------------------------------------------------------------------

rxjs6 中需要导入 import 'rxjs/Rx'

创建一个流并观察(订阅)它:

Observable.from([1,2,3,4]).filter(e => e%2 == 0).map(e => e*e).subscribe(e => console.log(e), err => console.error(err), () => console.log('结束'));

----------------------------以上写法不推荐---------------------------------------------

rxjs6版本, 可以直接使用 from() 来创建一个流, 所有filter, map等操作要写在 pipe()函数里面当做参数.

--------------------------------------------------------------------------------------------------------------------

Observable是一个流, subscribe监听一个流(订阅)它是一个观察者

模板本地变量 : <input #myField (keyup)="onKey(myField.value)"> 这样可以直接用string类型接收myField.value的值
用#xxx来声明一个变量,使用变量时不需要加#

angular的forms模块中有一个ReactiveFormsModule做响应式编程的模块,有一个对象FormControl可以用它来进行响应式表单验证

模板里面用 [formControl]="titleFilter" 把input和控制器里面的titleFilter绑在一起

private titleFilter: FormControl = new FormControl();

constructor(private productService: ProductService) {
this.titleFilter.valueChanges
.subscribe(
value => {xxxxxxxx;}
);
}

上面的例子是订阅它的valueChanges 事件流

Angular 组件间通信相关

-------------------------------------------------------------------------------------------------

父子组件间传递数据 子组件用@Input装饰的变量接收,父组件用 [xxx]=yyy的方式在子组件标签内传值,子组件数据的变化不会影响父组件

组件往父组件发射数据用 EventEmitter 可以这样写:

@Output('这里面可以写事件名字')
aObj: EventEmitter<Obj> = new EventEmitter;

aObj.emit(aObj)

EventEmitter<Obj> 表示往外发射的数据类型是一个Obj类型,那么用emit方法发射数据的aObj必须是一个Obj类型

捕获发射的数据需要用 (事件名字)="xxxxHandler($event)" 控制器里面用 xxxxHandler(event: Obj) 来接收这个event就是发射出来的Obj类型的数据, 如果@Output发射的EventEmitter对象名字(aObj)是xxxChange,并且@Input的名字也是xxx,那么可以直接在父组件中用[(xxx)]="yyy"这种语法双向绑定.

-----------------------------------------------------------------------------------------------------

中间人是两个组件共同的父组件,可以先捕获一个组件发射出来的数据 (事件名字)="xxxxHandler($event)" 然后在传给另一个子组件 [xxxxx]="xxxxxx"

-----------------------------------------------------------------------------------------------------

在父组件控制器中调用子组件的方法. 首先在父组件模板中 <app-child #child1></app-child> 给子组件声明一个模板本地变量

然后在控制器中用下面这个装饰器来声明一个ChildComponent类型的对象. 然后可以用 child1.xxx() 来调用子组件的方法.

@viewChild("child1")
child1: ChildComponent;

也可以直接在父组件的模板中用 (click)="child1.xxx()" 的方式来调用子组件的方法. 这两种方式都需要声明子组件的模板本地变量(尽量避免使用@viewChild这种方式调用方法,因为这会造成紧耦合)

-----------------------------------------------------------------------------------------------------

投影:可以把父组件的html投影到子组件中去,首先在子组件模板中用<ng-content></ng-content>标记一个投影点,然后在父组件中用 <app-child>要投影到子组件中的html<app-child>, 还可以有多个投影.如父组件模板中给需要投影的html一个类,那么子组件就用 <ng-content select=".xxx类名"></ng-content> 的方式来表名要把那一段代码投影到这上面.

Angular 表单相关

-------------------------------------------------------------------------------------------------

如果是模板表单,需要引入 FormsModule 如果是响应式表单需要引入 ReactiveFormsModule

angular会在所有表单上自动添加 ngForm 指令 ,会隐式创建一个 FormGroup类的实例,如果不想让angular接管表单,需要在表单上添加 ngNoForm . ngForm指令也可以添加到div上.移除html默认验证用 novalidate

ngForm 会扫描所有 标有 ngModel的子元素并将他们的值添加到表单数据模型中.

ngmodel在表单里面不用加 [()] 直接写一个 ngModel 就可以 ,他会隐式创建一个FormControl类的实例

可以用模板本地变量的方式给一个表单声明:#myForm="ngForm" 然后用 (ngSubmit)="onSubmit(myForm.value)" 这种方式指定提交的函数.以及把form里面 ngmodel元素的值传给函数

ngModelGroup 可以把一部分表单字段组成一个组,嵌套在表单里面,形成一个元素,也会隐式创建一个FormGroup的类的实例.<div ngModelGroup="useInfo">嵌套的表单元素</div>

----------------------------------------------------------------------------------------------------------

响应式表单 的三个类 : FormControl 可以理解为一个表单元素, FormGroup 多个FormControl的对象的形式(key, value)
FormArray 多个FormControl 的数组的形式. 提交用(submit)="onSubmit()"

响应式表单的指令: 如下图

(其中 formGroup和formControl指令不能嵌套存在, formGroup可以用在表单上, formControl适合绑定单独的input框, 在formGroup里面只能也必须使用带name的三个指令, 三个带name的指令不能用数据绑定的方式绑定)

构建数据模型的时候可以直接用 FormBuilder 需要在构造函数中注入进去 constructor(fb: FormBuilder) 简单例子:

constructor(private fb: FormBuilder) {
this.formModel = fb.group({
username: [''],
mobile: [''],
passwordsGroup: fb.group({
password: [''],
pconfirm: ['']
})
});
}

其中每个字段的[''](不一定加单引号,这里是因为都是字符串)里面都可以有三个字段,第一个是默认值,第二个是校验器,第三个是异步的校验器,angular预定义好的校验器是 Validators 这个类里面的静态方法.如 username: username: ['', [Validators.required, Validators.minLength(6)]],
可以用 let isValid: boolean = this.formModel.get('username').valid; 这种方式取出是否符合校验规则的值.符合为true
还可以用 let errors: any = this.formModel.get('username').errors; 这种方式取出校验错误信息.

自定义校验器的demo: 只有formModel里面所有字段都符合校验器,那么 formModel.valid才为true.
注意:自定义校验器如果通过的话,一定要返回 null.

------------------------------------------------------------------------------------------------------

mobileValidator(control: FormControl): any {
var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+d{8})$/;
let valid = myreg.test(control.value);
console.log("校验结果"+valid);
return valid ? null : {mobile: true};
}

equalValidator(group: FormGroup): any {
let password: FormControl = group.get('password') as FormControl;
let pconfirm: FormControl = group.get('pconfirm') as FormControl;
let valid: boolean = (password.value === pconfirm.value);
console.log('密码是否相等'+valid);
return valid ? null : {equal: true};
}

formModel: FormGroup;

constructor(private fb: FormBuilder) {
this.formModel = fb.group({
username: ['', [Validators.required, Validators.minLength(6)]],
mobile: ['', this.mobileValidator],
passwordsGroup: fb.group({
password: [''],
pconfirm: ['']
}, {validator: this.equalValidator})
});
}

------------------------------------------------------------------------------------------------------

注意,  判断校验是否正确 在模板中, 一种是  formModel.get('username').hasError('required') 还有就是 formModel.hashError('required', 'username')

原文地址:https://www.cnblogs.com/cccy0/p/9544437.html