从 Angular 2 组件内访问 `selector`

29

我正在尝试找出如何访问我们传递到 @Component 装饰器中的 selector

例如:

@Component({
  selector: 'my-component'
})
class MyComponent {
  constructor() {
     // I was hoping for something like the following but it doesn't exist
     this.component.selector // my-component
  }
}

最终,我想使用这个来创建一个指令,自动添加属性data-tag-name="{this.component.selector}",以便我可以使用Selenium查询可靠地通过选择器找到我的Angular元素。
我没有使用Protractor。
4个回答

36

使用ElementRef

import { Component, ElementRef } from '@angular/core'

@Component({
  selector: 'my-component'
})
export class MyComponent {
  constructor(elem: ElementRef) {
    const tagName = elem.nativeElement.tagName.toLowerCase();
  }
}

这可能是现在唯一的方法。旧的(现在已经损坏)方式更好,因为它不需要添加注入,并且可以在不需要实例的情况下访问,我在编写端到端测试以最小化重复时使用它。 - Ruan Mendes

9

已过时 请查看https://dev59.com/zFoU5IYBdhLWcg3wsod8#42579760

您需要获取与组件相关的元数据:

重要提示 当您运行AOT编译器时,注释会被剥离,因此如果您正在预编译模板,则该解决方案无效。

@Component({
  selector: 'my-component'
})
class MyComponent {
  constructor() {
    // Access `MyComponent` without relying on its name
    var annotations = Reflect.getMetadata('annotations', this.constructor);
    var componentMetadata = annotations.find(annotation => {
      return (annotation instanceof ComponentMetadata);
    });
    var selector = componentMetadata.selector // my-component
  }
}

这看起来很有前途,但如果我们没有告诉Reflect.getMetadata该如何查找MyComponent的元数据,它是如何知道的呢?当我调用Reflect.getMetadata('annotations')时,我目前遇到了一个错误。错误是Reflect.getMetadata('annotations', this, 'annotations')。看起来它需要两个额外的参数。 - Ruan Mendes
1
通过将this.constructor作为第二个参数传递,修复了你的答案。 - Ruan Mendes
2
请注明此答案适用的Angular 2版本 - 截至2.3.0发布,此答案似乎已过时。 - Neoheurist
抱歉,此内容无法翻译。 - noelm

8

如果您需要获取组件选择器的名称,但无法访问组件的ElementRef,则可以使用以下替代方法:

const components = [MyComponent];

for (const component of components) {
  const selector = component.ɵcmp.selectors[0][0];
  console.log(selector);
}

老实说,第一种方法感觉有点巧合,谁知道这个 ɵ 是不是只用于内部?我想把它包含在内,以便可能有人可以阐明一下?

所以,这可能是一个更安全的选择:

constructor(private factory: ComponentFactoryResolver) {
  const components = [MyComponent];

  for (const component of components) {
    const { selector } = this.factory.resolveComponentFactory(component);
    console.log(selector);
  }
}

1
第一种解决方案取决于内部/私有值。然而,第二种解决方案看起来很可靠。 - Ruan Mendes
2
第二个选项绝对是我迄今为止看到的最可靠的选择。感谢你指出这一点,德鲁。 - maxime1992
1
ComponentFactoryResolver在Angular v13中已被弃用。这很遗憾,因为我正在使用Angular元素,并且本来可以在AppModule构造函数中使用它来定义自定义元素,所以我无法注入ViewContainerRef。 - UKnoHowWeDo

7

从Angular v14.1开始,您可以这样做:

@Component({
  selector: 'my-component'
})
class MyComponent {
  constructor() {
     const metadata = reflectComponentType(MyComponent);
     const selector = metadata.selector // my-component
  }
}

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