如何在Angular 2中获得与ElementRef相关的组件的引用

RBa*_*iak 40 angular

我的模板中有这个组件:

<vector-editor  #scaleControl
                [x]="scaleX"
                [y]="scaleY"
                [z]="scaleZ" >               
</vector-editor>
Run Code Online (Sandbox Code Playgroud)

vector-editor结构如下:

export class VerticeControlComponent implements OnInit
{
    @Input() x: number;
    @Input() y: number;
    @Input() z: number;

    ...
}
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,我抓住了对#scaleControl使用的引用

@ViewChild('scaleControl') scaleControl: ElementRef;
Run Code Online (Sandbox Code Playgroud)

现在,如果我输出scaleControl到控制台,我得到这个结果:

在此输入图像描述

可以看出,引用不是null,并且我的组件的所有属性都在那里.我想访问这些属性,但在代码中实际的类型scaleControl是,ElementRef而不是VectorEditorControl在输出中看到.因此,我不允许使用TypeScript this.scaleControl.x.

我也试着ElementRef像这样投

var temp = <VectorEditorControl>this.scaleControl
Run Code Online (Sandbox Code Playgroud)

但我得到一个错误,告诉我,我不能投ElementRefVectorEditorControl

最后,我试图访问,this.scaleControl.nativeElement但它是未定义的...

我在这里错过了什么?

yur*_*zui 98

您应该了解有关使用@ViewChild属性装饰器的以下信息.

它使用以下元数据属性:

  • selector - 用于查询的指令类型或名称.
  • read - 从查询的元素中读取不同的标记.

来自源代码:

export interface ViewChildDecorator {
  /**
   * You can use ViewChild to get the first element or the directive matching 
   * the selector from the
   * view DOM. If the view DOM changes, and a new child matches the selector,
   * the property will be updated.
   *
   * View queries are set before the `ngAfterViewInit` callback is called.
   *
   * **Metadata Properties**:
   *
   * * **selector** - the directive type or the name used for querying.
   * * **read** - read a different token from the queried elements.
   */
  (selector: Type<any>|Function|string, {read}?: {read?: any}): any;
  new (selector: Type<any>|Function|string, {read}?: {read?: any}): ViewChild;
}
Run Code Online (Sandbox Code Playgroud)

如果您不提供read参数,@ViewChild()将返回:

  • 组件实例,如果有.
  • ElementRef 实例,如果没有应用组件
  • 如果设置了read属性,则来自查询元素的不同标记

因此,如果你想ElementRef从angular2 component(VerticeControlComponent)的孩子那里获得,你需要明确地告诉我们使用read: ElementRef:

@ViewChild('scaleControl', {read: ElementRef}) scaleControl: ElementRef;
Run Code Online (Sandbox Code Playgroud)

然后在ngAfterViewInit挂钩或更高版本中你可以编写this.scaleControl.nativeElement来获取DOM元素.

更新

我早写的:

  • 如果设置了read属性,则来自查询元素的不同标记

现在我想添加我们可以阅读的内容:

  • ElementRef

  • TemplateRef

  • ViewContainerRef

  • 提供商

Provider这里的意思是什么?

这意味着如果我们在特定元素上定义任何提供者(在组件或指令中),那么我们就可以读取它.

@Component({
  selector: 'child',
  template: `
   <h2>I'm child</h2>
  `,
  providers: [
    {
      provide: 'test', useValue: 'x'
    }
  ]
})
export class ChildComponent {

}
Run Code Online (Sandbox Code Playgroud)

所以在这个组件的消费者中我们可以写

@ViewChild(ChildComponent, { read: 'test' }) providerToken: string;
Run Code Online (Sandbox Code Playgroud)

获得价值x.

也可以看看:

  • 要直接获取组件,可以指定子类型,而不是将其用作ElementRef:`@ ViewChild('scaleControl')scaleControl:VerticeControlComponent;` (3认同)
  • 再加上1个最好的扩展 (2认同)

Ser*_*iro 5

在撰写本文时,我建议使用以下方法:

@ViewChild('scaleControl') scaleControl: ElementRef<VerticeControlComponent>;
Run Code Online (Sandbox Code Playgroud)

然后,您可以访问这两种类型。

  • ElementRef:使用scaleControl
  • VerticeControlComponent:使用scaleControl.nativeElement

  • 这对我不起作用。`scaleControl.nativeElement` 提供一个原生 HTML 元素,而不是 `VerticeControlComponent` 的实例。 (2认同)