文章目录
EventEmitter 类
EventEmitter用在带有 @Output
指令的组件中,以同步或异步方式发出自定义事件,并通过订阅实例来为这些事件注册处理器。
// EventEmitter类 继承自Rxjs的Subject。(EventEmitter 类派生自 Observable。)
class EventEmitter<T> extends Subject<T> {
/**
* 构造函数,用于创建此类的实例,该实例可以同步或异步发送事件。
* isAsync 默认值为false,表示同步传递事件。为 true 时,异步传递事件。
* 泛型T,表示要发射的值和被订阅的值类型
*/
constructor(isAsync?: boolean): EventEmitter<T>
// 发出包含给定值的事件。value为要发出的值,类型为T。
emit(value?: T): void
// 注册此实例发出的事件的处理器。
subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription
}
使用 EventEmitter 自定义事件
Directives(指令) 通常使用 Angular 的 EventEmitter 引发自定义事件:
- 该指令创建一个
EventEmitter
并将其对外暴露为属性。 - 该指令调用
EventEmitter.emit(data) 发出事件
,传入消息数据,该消息数据可以是任何东西。 - 父指令通过绑定到该属性来监听事件,并通过传入的
$event
对象接收数据。
子组件把数据发送到父组件 @Output、EventEmitter
@Output()
在子组件中标记了一个属性,作为数据从子组件传递到父组件的途径。
子组件使用 @Output() 属性来引发事件,以通知父组件这一变化。为了引发事件, @Output() 必须是 EventEmitter 类型,它是 @angular/core 中用来发出自定义事件的类。
// 子组件
import { Output, EventEmitter } from '@angular/core';
export class ItemOutputComponent {
/**
* @Output() - 一个装饰器函数,它把该属性标记为数据从子组件进入父组件的一种途径
* newItemEvent - 这个 @Output() 的名字
* EventEmitter<string> - 这个 @Output() 的类型
* new EventEmitter<string>() - 使用 Angular 来创建一个新的事件发射器,它发出的数据是 string 类型的。
*/
@Output() newItemEvent = new EventEmitter<string>();
addNewItem(value: string) {
this.newItemEvent.emit(value);
}
}
// 子组件模板
<label for="item-input">Add an item:</label>
<input type="text" id="item-input" #newItem>
<button (click)="addNewItem(newItem.value)">Add to parent's list</button>
// 父组件
export class AppComponent {
items = ['item1', 'item2', 'item3', 'item4'];
addItem(newItem: string) {
this.items.push(newItem);
}
}
// 父组件模板中 使用子组件
<app-item-output (newItemEvent)="addItem($event)"></app-item-output>
父组件修改子组件中的数据 @Input
子组件或指令中的 @Input()
装饰器表示该属性可以从其父组件中获取值。
/**
* 父组件模板
* 使用子组件的 selector (<app-item-detail>) 作为父组件模板中的指令。
* 使用属性绑定把子组件的 item 属性绑定到父组件的 currentItem 属性上。
*/
<app-item-detail [item]="currentItem"></app-item-detail>
// 父组件
export class AppComponent {
currentItem = 'Television';
}
// 子组件模板
<p>
Today's item: {{item}}
</p>
// 子组件
import { Component, Input } from '@angular/core';
export class ItemDetailComponent {
@Input() item = '';
}
监视 @Input() 的变更的两种方式
方式一:setter拦截器
// 子组件模板
<p>
Today's item: {{_item}}
</p>
// 子组件
import { Component, Input } from '@angular/core';
export class ItemDetailComponent {
_item: string = '';
@Input() set item(value: string){
this._item = value;
// 每当数据发送改变时要执行的操作
this.valueChangeHandler()
};
valueChangeHandler() {
console.log('数据被父组件更改了,我应该相应地做点别的操作!');
}
}
方式二:OnChanges生命钩子
// 子组件模板
<p>
Today's item: {{item}}
</p>
// 子组件
import { Component, Input, OnChanges, SimpleChanges, } from '@angular/core';
export class ItemDetailComponent {
@Input() item = '';
ngOnChanges(changes: SimpleChanges) {
console.log('item的最新值:', changes.item.currentValue, 'item的旧值:', changes.item.previousValue;)
// 每当数据发送改变时要执行的操作
this.valueChangeHandler()
}
valueChangeHandler() {
console.log('数据被父组件更改了,我应该相应地做点别的操作!');
}
}
ngOnChanges钩子和SimpleChanges对象
在Angular生命周期钩子的执行顺序中,ngOnChanges()排在第一位。
生命钩子 | 用途 | 时机 | 注意事项 |
---|---|---|---|
ngOnChanges() | ngOnChanges() 是一个生命周期钩子,当组件或指令的任何一个可绑定属性(输入属性)发生变化时调用。 定义一个 ngOnChanges() 方法来处理这些变更。当 Angular 设置或重新设置数据绑定的输入属性时响应。 该方法接受当前和上一属性值的 SimpleChanges 对象。ngOnChanges() 方法获取了一个对象,它把每个发生变化的属性名都映射到了一个SimpleChange对象, 该对象中有属性的当前值和前一个值。这个钩子会在这些发生了变化的属性上进行迭代,并记录它们。 | 如果组件绑定过输入属性,那么在 ngOnInit() 之前以及所绑定的一个或多个输入属性的值发生变化时都会调用。 如果至少发生了一次变更,则该回调方法会在默认的变更检测器检查完可绑定属性之后、视图子节点和内容子节点检查完之前调用。 | 1. OnChanges发生的非常频繁,所以你在这里执行的任何操作都会显著影响性能。 2. 如果你的组件没有输入属性,或者你使用它时没有提供任何输入属性,那么框架就不会调用 ngOnChanges()。 3. 当输入属性的 引用 发生改变时,才会触发钩子ngOnChanges()。比如说,如果输入属性是一个对象hero: Hero,而父组件只修改了hero.name的值,则不会触发子组件的ngOnChanges()。 |
SimpleChanges:用 SimpleChange 对象表示的变更的哈希表。
export declare interface SimpleChanges {
[propName: string]: SimpleChange;
}
export declare class SimpleChange {
previousValue: any;
currentValue: any;
firstChange: boolean;
constructor(previousValue: any, currentValue: any, firstChange: boolean);
// 检查新值是否是首次赋值的。
isFirstChange(): boolean;
}
组件要如何实现本接口来定义一个输入属性的变更处理器?
@Component({selector: 'my-cmp', template: `...`})
class MyComponent implements OnChanges {
// 输入属性
@Input() prop: number = 0;
// 变更处理器
ngOnChanges(changes: SimpleChanges) {
// changes.prop contains the old and the new value...
}
}
使用变更检测钩子
https://angular.cn/guide/lifecycle-hooks#using-change-detection-hooks