chatgpt:
在 Angular 中,@ViewChild
是一个装饰器,用于在组件类中获取对模板中子元素、指令或组件的引用。它允许你在组件类中访问模板中的特定元素,以便可以直接操作或与其交互。
例如,如果你在模板中有一个子组件或一个具有本地引用的元素,你可以使用 @ViewChild
装饰器在组件类中获取对该元素的引用。这样,你就可以在组件类中调用该元素的方法、访问其属性或者订阅其事件。
这是一个简单的示例,演示了如何在 Angular 组件中使用 @ViewChild
:
ts
import { Component, ViewChild, ElementRef } from '@angular/core';
@Component({
selector: 'app-example',
template: `
<div #myElement>Some content</div>
`
})
export class ExampleComponent {
@ViewChild('myElement', { static: true }) myElementRef: ElementRef;
ngAfterViewInit() {
// 可以在这里访问和操作子元素
console.log(this.myElementRef.nativeElement.textContent); // 获取子元素的文本内容
this.myElementRef.nativeElement.style.color = 'red'; // 修改子元素的样式
}
}
在这个例子中,@ViewChild
装饰器用于获取模板中带有 #myElement
本地引用的 <div>
元素的引用,并在 ngAfterViewInit
生命周期钩子中对其进行操作。
需要注意的是,@ViewChild
装饰器接受一个选择器作为参数,用于定位模板中的元素。在这里,我们使用了 #myElement
选择器来获取对应的元素引用。
另外,{ static: true }
是 @ViewChild
的一个配置选项,用于指定何时应该去查询视图中的元素。{ static: true }
表示在组件初始化时就会进行查询,{ static: false }
表示在首次调用 ngAfterViewInit
生命周期钩子时进行查询。
Angular For Beginners - 25. @ViewChild()
当使用 JavaScript 时,可以使用 getElementById
来获取特定的 HTML 元素对象。但在 Angular 中,并没有类似于 getElementById
的直接函数。相反,Angular 提供了 @ViewChild
这样的装饰器,用于在组件类中获取模板中特定元素的引用,从而实现类似的功能。
但是,getElementById
的参数与 @ViewChild
的参数有很大的不同。 不能传 html 标签或 css 选择器给 @ViewChild
,传进 @ViewChild
中的参数分以下 4 种:
1.
pokemon-list.compoment.html
增加一个 template ref #pokemonRef
:
html
<table>
<thead>
<th>Name</th>
<th>Index</th>
</thead>
<tbody>
<app-pokemon-detail
#pokemonRef // new code
*ngFor="let pokemon of pokemons"
[detail]="pokemon"
(remove)="handleRemove($event)"
>
<h1>-----------------------</h1>
<h2>============================</h2>
<h3></h3>
</app-pokemon-detail>
</tbody>
</table>
2.
多个孩子用 @ViewChildren
,单个用 @ViewChild
。
@ViewChild
只能在 View 渲染之后才能使用:
pokemon-list.compoment.ts
:
因为 ngAfterViewInit
继承了 AfterViewInit
, 所以 PokemonListComponent
需要 implement AfterViewInit
:
ts
export class PokemonListComponent implements OnInit, AfterViewInit {
完整代码如下:
ts
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, ViewChildren } from '@angular/core';
import { Pokemon } from 'src/app/models/pokemon';
import { PokemonService } from 'src/app/services/pokemon.service';
@Component({
selector: 'app-pokemon-list',
templateUrl: './pokemon-list.component.html',
styleUrls: ['./pokemon-list.component.css'],
})
export class PokemonListComponent implements OnInit, AfterViewInit {
// pokemons!: Pokemon[];
pokemons: Pokemon[] = [];
// 这里不是 @ViewChild, 否则log 为 undefined
// 而是 @ViewChildren,使用了 for 循环, 孩子数多于一个,有3个。
@ViewChildren('pokemonRef') pokemonRef!: ElementRef;
constructor(private pokemonService: PokemonService) {}
// 新代码
ngAfterViewInit(): void {
// throw new Error('Method not implemented.');
console.log("ngAfterViewInit begin")
console.log(this.pokemonRef)
console.log("ngAfterViewInit end")
}
handleRemove(event: Pokemon) {
this.pokemons = this.pokemons.filter((pokemon: Pokemon) => {
return pokemon.id !== event.id;
});
}
ngOnInit(): void {
// 填充 pokemons 属性
// this.pokemons = this.pokemonService.getPokemons();
this.pokemonService.getPokemons().subscribe((data: Pokemon[]) => {
console.log(data);
this.pokemons = data;
});
}
}