有没有办法从 Angular 中的组件内部检查 @Output 连接?

Is there a way to check for @Output wire up from within a component in Angular?

在组件的 ngOnInit 方法中,@Input 值将被绑定,因此您可以检查组件上的那些属性,但似乎没有办法检查 @Output 事件绑定。我想知道 @Output 是否连接到组件上。

(使用 Angular 和 TypeScript)

import {Component, Output, EventEmitter} from '@angular/core';

@Component({
    selector: 'sample',
    template: `<p>a sample</p>`
})
export class SampleComponent {
    @Output() cancel = new EventEmitter();
    
    ngOnInit() {
        // would like to check and see if cancel was used
        // on the element <sample (cancel)="doSomething()"></sample> 
        // or not <sample></sample>
    }
}

以下代码应该有效:

import {Component, Output, EventEmitter, OnInit} from 'angular2/core';
import {ObservableWrapper} from 'angular2/src/facade/async';

@Component({
    selector: 'sample',
    template: `<p>a sample</p>`
})
export class SampleComponent implements OnInit {
    @Output() cancel: EventEmitter<any> = new EventEmitter();

    private isCancelUsed: boolean;

    ngOnInit(): void {
        this.isCancelUsed = ObservableWrapper.hasSubscribers(this.cancel);
    }
}

user1448982 相同的方法,但不使用 ObservableWrapper,这意味着平台代码不会通过 api.

公开使用。

(使用 Angular 2 RC1 和 TypeScript)
注意:这只从 2.0.0-beta.16 和更高版本开始工作

import {Component, Output, EventEmitter} from '@angular/core';

@Component({
    selector: 'sample',
    template: `<p>a sample</p>`
})
export class SampleComponent {
    @Output() cancel = new EventEmitter();
    private isCancelUsed = false;

    ngOnInit() {
        this.isCancelUsed = this.cancel.observers.length > 0;
    }
}

Plunker

ObservableWrapper.hasSubscribers 方法在内部执行此行,因此您可以在此处执行相同的操作。

使用 TypeScript 时,如果 Angular 最终将 EventEmitterSubject 更改为 [=16= =], 因此 .observers 属性).

更新 (03 / 2022)

observers 属性自 rxjs v7 起已弃用。您现在可以使用一个布尔值来指示主题是否正在使用,而不是检查观察者数组的长度。

// Old approach
this.isCancelUsed = this.cancel.observers.length > 0;

// New approach
this.isCancelUsed = this.cancel.observed;

Angular 12 删除了 EventEmitter#observables 字段,因此接受的答案不再有效。

现在的替代解决方案是转换为 Subject:

get hasOutputEventSubscriber() {
    return (this.cancel as Subject).observers;
}

请注意,此 属性 也已弃用,将在 rxjs v8 中删除。一个面向未来的解决方案是为 EventEmitter 编写自定义包装器 class。

这是一个不依赖于 Angular 或 rxjs 的任何内部结构的未来证明示例。这是一个围绕 EventEmitter 的简单包装器,它公开了一个 subscriberCount 属性,当订阅者是 added/removed.

时,它会自动 incremented/decremented
class WatchedEventEmitter extends EventEmitter<any> {
    private _subscriberCount = 0;
    get subscriberCount(): number {
        return this._subscriberCount;
    }

    subscribe(next?: (value: any) => void, error?: (error: any) => void, complete?: () => void): Subscription {
        ++this._subscriberCount;
        return super.subscribe(next, error, complete);
    }

    unsubscribe() {
        --this._subscriberCount;
        super.unsubscribe();
    }
}

用法示例:

@Component({template: `
    {{click.subscriberCount|json}}
    <span *ngIf="cancel.subscriberCount">
        <button mat-icon-button (click)="cancel.emit()">Click Me</button>
    </span>
    
    <span *ngIf="!cancel.subscriberCount">No Subscribers</span>
`})
export class SomeComponent {
    @Output() cancel = new WatchedEventEmitter();
}

当前版本 Angular 13 检查是否有任何 observer/callback 提供你可以使用 this.cancel.observed 它将 return boolean

import {Component, Output, EventEmitter} from '@angular/core';

@Component({
    selector: 'sample',
    template: `<p>a sample</p>`
})
export class SampleComponent {
    @Output() cancel = new EventEmitter();
    private isCancelUsed = false;

    ngOnInit() {
        this.isCancelUsed = this.cancel.observed;
    }
}