Angular v8中@ViewChild的static属性设为true的场景及影响
何时为Angular的@ViewChild/@ContentChild设置{ static: true }?
Angular 8强制要求给@ViewChild和@ContentChild添加static标志,确实容易让人困惑——毕竟文档说大多数时候用{ static: false }就行。我来梳理清楚什么时候该用true,以及这么做会带来什么影响:
什么时候应该设static: true?
- 你需要在
ngOnInit里访问查询结果,且目标元素不会被结构型指令影响:如果你的模板里的元素是固定存在的(没有被*ngIf、*ngFor这类指令包裹),那它会在组件初始化阶段就出现在DOM中。这时候设static: true,就能在ngOnInit里直接拿到元素/组件的引用,不用等到ngAfterViewInit。 - 早于视图初始化的逻辑需要用到查询结果:比如你要在动画初始化、某些自定义的初始化钩子(早于
ngAfterViewInit)里用到这个元素,static: true能确保在这些阶段查询已经完成,不会拿到undefined。
设置static: true的影响
- 查询执行时机更早:静态查询会在组件模板首次编译完成后立即执行,比动态查询早得多——动态查询要等到
ngAfterViewInit/ngAfterContentInit之后才会跑。 - 不会响应DOM的动态变化:这是最关键的一点!静态查询只执行一次(组件初始化时),如果后续元素因为
*ngIf被移除、*ngFor更新导致DOM重构,静态查询的结果不会更新。如果你的元素是动态变化的,用static: true会导致后续拿不到正确的引用,甚至一直是undefined。 - 轻微的性能优化:因为只查询一次,避免了动态查询每次视图变化都要重新查询的开销。当然这个优化很微小,只有在大量静态元素查询的场景下才会有明显感受。
为了更直观,举两个例子:
正确使用static: true的场景
@Component({ template: `<h1 #pageTitle>我的页面标题</h1>` }) export class PageComponent implements OnInit { @ViewChild('pageTitle', { static: true }) pageTitle: ElementRef; ngOnInit() { // 这里可以直接拿到标题元素,因为它是固定存在的 console.log('页面标题:', this.pageTitle.nativeElement.textContent); } }
错误使用static: true的场景(元素被*ngIf控制)
@Component({ template: `<div *ngIf="isVisible" #dynamicBox>动态显示的盒子</div>` }) export class DynamicComponent implements OnInit { @ViewChild('dynamicBox', { static: true }) dynamicBox: ElementRef; isVisible = false; ngOnInit() { // 这里dynamicBox是undefined,因为初始化时isVisible为false,元素还没渲染 console.log(this.dynamicBox); // 输出undefined } ngAfterViewInit() { this.isVisible = true; // 即使元素现在渲染了,静态查询也不会更新结果,还是undefined console.log(this.dynamicBox); } }
反过来,{ static: false }会在视图初始化完成后执行查询,并且会监听DOM的动态变化,自动更新查询结果——这就是为什么文档说大多数情况用它就够了,毕竟很多元素都会受到结构型指令的影响。
内容的提问来源于stack exchange,提问作者Gil Epshtain
相关产品推荐
相关产品推荐

