检查组件是否有输出

17

考虑以下组件:

@Component({
  selector: 'app-test'
  template: 'Hello!'
}}
export class TestComponent {
  @Output() readonly selectionChange = new EventEmitter<SomeTypeHere>();
}

随着电话的呼叫:

<app-test (selectedChange)="selectedChangeHandler($event)"></app-test>
请注意,我已经写了selectedChange而不是正确的输出名称selectionChange。启用标志strictTemplates的Angular 9对我没有任何帮助。它默默失败了。有趣的部分是,如果我为@Input做同样的事情,应用程序会捕获错误并且不会编译。
是否有任何方法可以在尝试“监听”不存在的@Output时抛出错误?

1
之前的Angular版本有没有出现过任何错误?我认为它从未在此处抛出任何错误。 - Aravind
@Aravind 不,它从未抛出错误。我在问是否可能。提前致谢。 - dev_054
为什么你想要抛出错误?有特定的需求吗?我正在尝试理解你的问题。 - Aravind
@Aravind 嗯,我正在与许多开发人员一起开发企业应用程序,因此拥有某种信息/警告/错误很重要。 有时某人会更改/删除共享库中的 @Output(),甚至在应用程序中忘记删除调用...而且由于我们没有编译错误(就像对于@Input()一样),我们无法找到确切导致某些问题的原因(甚至是不保留代码中的垃圾)。 单元测试可能有帮助? 也许,但目前由于时间限制尚不可能。 - dev_054
4个回答

5
没有错误抛出,因为在Angular中事件绑定不仅与@OutputEventEmitter一起使用,还可用于监听DOM事件,例如clickkeyup等。甚至可以用来监听自定义事件。例如,如果您在子组件中创建并发射一个自定义事件:
constructor (private el: ElementRef) {}
ngOnInit(): void {
    const domEvent = new CustomEvent('selectedChange', { custom: true });
    this.el.nativeElement.dispatchEvent(domEvent);
}

然后在父组件中,您可以通过其名称捕获它:

<app-test (selectedChange)="selectedChangeHandler($event)"></app-test>

Angular 内部使用 target.addEventListener(type, listener [, options]);(您可以通过下面的链接来确认),其中 type 可以是任何字符串。
这就是为什么它不会抛出任何异常,即使找不到匹配的 @OutputlistenToElementOutputs

DefaultDomRenderer2.listen

EventManager.addEventListener

DomEventsPlugin.addEventListener


嘿,@Kirill Simonov,谢谢您的回答!根据您的说法:“由于Angular中的事件绑定不仅与@Outputs和EventEmitters一起使用,而且还用于监听DOM事件,例如点击、keyup等”,那么为什么如果您传递一个不存在的@Input()(请记住,输入具有相同的特征:可以是全局的,如disabledid等),Angular会抛出错误?为什么对于@Input可以工作,但是对于@Output却不行?另外,我正在尝试找到一种方法来警告/抛出错误,如果传递了一个不存在的@Output - dev_054
1
@dev_054,这是因为属性集受DOM元素、指令或组件现有属性的限制,因此Angular可以轻松检查该属性是否存在。另一方面,事件使用addEventListener绑定(我会在我的答案中添加一些链接来展示它)。我认为这是有意为之的,这样开发人员就可以使用自己的自定义事件进行事件绑定。我相信没有办法在编译时禁用此行为。尽管一些IDE(如IntelliJ Idea)可能会突出显示这些位置并显示警告。 - Kirill Simonov
@dev_054 记住,你也可以使用单向绑定来绑定 HTML 属性,使用 [attr.any-attribute],这种情况下也不会抛出错误。 - Kirill Simonov

1
这应该对你有用。
ngOnInit() : void {
 if(this.selectionChange.observers.length > 0){
   console.log("Nice coding");
 }else{
  console.log("Something is wrong!!");
}

0

您的问题没有直接的解决方案,但是有些情况可以得到覆盖。

  1. 如果您有任何输出在100%的地方使用,例如按钮click事件,那么您可以将其作为选择器的一部分,即selector:'app-test [selectionChange]'。此外,您还可以这样做:selector:'app-test [selectionChange],app-test [click]',意思是需要clickselectionChange
  2. 如果您正在重构代码并重命名输出,例如将selectionChange重命名为selectedChange,那么您可以使用此选择器:selector:'app-test:not([selectionChange])'强制用户进行更新。

-3
如果你正在使用 VS Code,你可以安装这个扩展:Angular Language Service 当一个方法或属性未定义时会抛出警告。这个扩展适用于输出和输入(以及 attrs 等等...)。

Identifier 'XXXvalidateProvider' is not defined.


你的示例展示了一个@Input。对于@Output,Angular语言服务没有任何帮助。如果需要我澄清问题,请告诉我。 - dev_054
对于一个 @Output,您将看到相同的错误消息。 - srgrcp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接