3

一 引言

Angular @ViewChild 装饰器是您在学习 Angular 时会遇到的第一个装饰器之一,因为它也是最常用的装饰器之一。
装饰器@ViewChild是用来获取模板变量的元素的,当组件渲染完成后:
会更新为从dom上找到第一个匹配的组件或指令或纯 HTML 元素。

二 我们什么时候需要@ViewChild 装饰器?

很多时候,我们直接在模板中协调多个自定义组件和 HTML 元素或指令,而无需使用AppComponent类。
但情况并非总是如此!有时,AppComponent 可能需要引用其模板中包含的某些元素,以调解它们的交互。如果是这样,那么我们可以在AppComponent通过查询模板获取对这些模板元素的引用并将它们注入到类中:这就是@ViewChild 的用途。

元数据属性:
selector - 通过选择器(如元素名、指令名或组件名)来指定要查询的元素或指令。
read - 用于从查询到的元素中读取不同的令牌。(至少存在三种令牌:ElementRef、AComponent、SelectDirective)
static - true 以在变更检测运行之前求解查询结果, false 则在变更检测之后求解。默认值为 false。

三 @ViewChild 示例

使用 @ViewChild 注入组件

v层:

<app-demo>this DemoComponent</app-demo>

c层:

export class AppComponent implements OnInit{
  @ViewChild(DemoComponent, {static: true})
  demo!: DemoComponent;

  ngOnInit(): void {
    console.log("ngOnInit", this.demo)
  }
}

效果:
image.png

使用 @ViewChild 注入纯 HTML 元素

v层:

<h2 #demo>对 DOM 元素的引用</h2>

c层:

export class AppComponent implements OnInit{
  @ViewChild('demo', {static: true})
  demo!: ElementRef;

  ngOnInit(): void {
    console.log("ngOnInit", this.demo)
  }
}

效果:
image.png

使用 @ViewChild 注入指令

v层:

<app-demo appMyDirective>this DemoComponent</app-demo>

c层:

export class AppComponent implements OnInit{
  @ViewChild(MyDirectiveDirective, {static: true})
  demo!: MyDirectiveDirective;

  ngOnInit(): void {
    console.log("ngOnInit", this.demo)
  }
}

效果:四
image.png

三 @ViewChild 模板查询的范围是什么?

@ViewChild 的查询范围是当前组件的模板。具体来说,它会查找第一个匹配的元素或指令(除非使用了 {static: false} 选项,这将导致它在 ngAfterViewInit 生命周期钩子中查询,这可能会找到由 *ngFor 或其他结构型指令动态创建的多个元素中的一个)
示例一:
父组件v层

<app-demo appMyDirective>this DemoComponent</app-demo>

子组件v层:

<h2 #demo>demo works!</h2>

在父组件引入子组件的元素:

export class AppComponent implements OnInit{
  @ViewChild("demo", {static: true})
  demo!: ElementRef;

  ngOnInit(): void {
    console.log("ngOnInit", this.demo)
  }
}

效果:
image.png
所以:@ViewChild 的查询范围是当前组件的模板。

四 AfterViewInit 生命周期钩子

调用时机:在Angular完成视图初始化之后,并且所有子组件的视图也已经被初始化之后,AfterViewInit 钩子会被调用。

与 ngOnInit 的区别:ngOnInit 是在Angular完成组件的初始化之后,但在视图渲染之前被调用的。
angular生命周期:
image.png

元数据属性:
static - true 以在变更检测运行之前求解查询结果, false 则在变更检测之后求解。默认值为 false。

一下实例分别设置static的值为true和false。

export class AppComponent implements OnInit, AfterViewInit{
  @ViewChild(DemoComponent, {static: true})
  demo!: DemoComponent;

  ngOnInit(): void {
    console.log(" ngOnInit demoComponent title", this.demo.title)
  }

  ngAfterViewInit(): void {
    console.log("ngAfterViewInit demoComponent title", this.demo.title);
  }
}

static的值设置为true时:
image.png
static的值设置为false时:
image.png

总结

selector - 通过选择器(如元素名、指令名或组件名)来指定要查询的元素或指令。
read - 用于从查询到的元素中读取不同的令牌。(至少存在三种令牌:通过元素名选择器查询出的元素被包装为ElementRef、通过组件选择查询出来的元素就是组件本身、通过指令选择查询出来的元素就是指令本身)
static - 设置查询时机


吴季分
390 声望13 粉丝