文章目录
提示:以下是本篇文章正文内容,下面案例可供参考
一、@Input
在父组件中,我们有一个message属性,我们想将其传递给子组件以显示。
ParentComponent (parent.component.ts)代码如下(示例):
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<app-child [childMessage]="parentMessage"></app-child>
`,
})
export class ParentComponent {
parentMessage = 'message from parent';
}
ChildComponent (child.component.ts)代码如下(示例):
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: `
{{ childMessage }}
`,
})
export class ChildComponent {
@Input() childMessage: string;
}
二、@Output
在子组件中,我们有一个按钮,当点击这个按钮时,我们想将一个事件发送到父组件。
ChildComponent (child.component.ts)如下(示例):
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
})
export class ChildComponent {
@Output() messageEvent = new EventEmitter<string>();
sendMessage() {
this.messageEvent.emit('Hello from Child Component!');
}
}
ParentComponent (parent.component.ts)如下(示例):
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<app-child (messageEvent)="receiveMessage($event)"></app-child>
`,
})
export class ParentComponent {
childMessage: string;
receiveMessage($event: string) {
this.childMessage = $event;
}
}
三、@ViewChild
ChildComponent (child.component.ts)代码如下(示例):
import { Component } from '@angular/core';
@Component({
selector: 'app-child',
template: `
Welcome to the app!
`,
})
export class ChildComponent {
greet() {
alert('Hello from Child Component!');
}
}
ParentComponent (parent.component.ts)代码如下(示例):
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'app-parent',
template: `
<app-child></app-child>
<button (click)="callChildMethod()">Call Child Method</button>
`,
})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) childComponent: ChildComponent;
ngAfterViewInit() {
// ViewChild is set after the view has been initialized
this.childComponent.greet();
}
callChildMethod() {
this.childComponent.greet();
}
}
四、@Input、@Output、@ViewChild和RXJS结合使用案例
@Input,@Output 与 RxJS 非常好地结合在一起,特别是在处理异步操作和复杂事件流时。
4.1 @Input 和 RxJS
如果你的 @Input 属性频繁改变,你可能会想要对这些改变进行响应,例如,执行一个复杂的计算,或者从服务器加载相关的数据。在这种情况下,你可以使用 RxJS 的 Subject 和 switchMap 操作符:
private _data = new Subject<Data>();
@Input()
set data(value: Data) {
this._data.next(value);
}
ngOnInit() {
this._data.pipe(
switchMap(data => this.loadData(data))
).subscribe(result => {
// 处理结果
});
}
每次 @Input 属性改变时,都会调用 loadData 函数,并自动取消之前的调用,如果它还在执行的话。
4.2 @Output 和 RxJS
@Output 属性通常是 EventEmitter 的实例,但 EventEmitter 本身就是 RxJS Subject 的子类,所以你可以用所有 RxJS 操作符处理 @Output 事件:
@Output() event = new EventEmitter<Event>();
ngOnInit() {
this.event.pipe(
debounceTime(500)
).subscribe(e => {
// 处理事件,但如果在500毫秒内有新事件,这个事件将被忽略
});
}
这样,你可以使用 debounceTime 操作符来防止事件的频繁触发。
4.3 @ViewChild 和 RxJS
可以在一个 @ViewChild 查询的结果上使用 RxJS 操作符。例如,你可能有一个视图子组件,这个子组件有一个返回 Observable 的方法,你可以在这个 Observable 上使用 switchMap,mergeMap,concatMap 等操作符:
@ViewChild(ChildComponent) child: ChildComponent;
ngOnInit() {
this.child.getData().pipe(
switchMap(data => this.processData(data))
).subscribe(result => {
// 处理结果
});
}
这样,每次子组件的数据改变时,都会调用 processData 函数,并自动取消之前的调用,如果它还在执行的话。
五、总结
相同点:
都是装饰器,用来标注类的成员变量。都用于实现组件之间的交互。
不同点:
@Input:它允许外部组件或者说父组件向子组件传递数据。它相当于子组件的公开属性,可以接收父组件的输入。@Input 装饰的变量表示输入属性,我们可以在模板表达式中绑定到这个输入属性上。
@Output:它允许子组件向父组件发送事件和数据。@Output 装饰的变量通常是 EventEmitter 的实例,用来发射事件。当子组件需要通知父组件某个事件时,可以调用这个 EventEmitter 的 emit 方法,然后父组件可以绑定到这个事件上。
@ViewChild:它允许一个组件内部访问其子组件的实例。使用此装饰器,父组件可以直接调用子组件的方法或访问其数据成员。@ViewChild 接收一个类类型或者模板引用变量名,然后会返回对应的类实例或者模板引用变量的值。
@Input 和 @Output 主要用于父子组件之间的数据交互,而 @ViewChild 则更多的是用于在一个组件内部访问其子组件。