在大多数情况下,您将希望使用 {static: false}
。这样设置将确保找到依赖于绑定解析的查询匹配项(如结构性指令*ngIf等
)。
何时使用static: false
的示例:
@Component({
template: `
<div *ngIf="showMe" #viewMe>Am I here?</div>
<button (click)="showMe = !showMe"></button>
`
})
export class ExampleComponent {
@ViewChild('viewMe', { static: false })
viewMe?: ElementRef<HTMLElement>;
showMe = false;
}
static: false
将成为Angular 9中的默认后备行为。在此处和此处了解更多。
{ static: true }
选项是用于支持动态创建嵌入式视图。当您动态创建视图并希望访问TemplateRef
时,您将无法在ngAfterViewInit
中这样做,因为这会导致ExpressionHasChangedAfterChecked
错误。将静态标志设置为true将在ngOnInit中创建视图。
然而:
在大多数其他情况下,最佳实践是使用{static: false}
。
但要注意,{ static: false }
选项将成为Angular 9中的默认设置。这意味着不再需要设置静态标志,除非您想使用static: true
选项。
您可以使用Angular CLI的ng update
命令自动升级当前的代码库。
有关此内容的迁移指南和更多信息,请单击此处和此处。
#静态查询和动态查询有什么区别?
@ViewChild()和@ContentChild()查询的静态选项确定查询结果何时可用。
对于静态查询(static: true),查询解析一旦视图创建完成但在变更检测运行之前进行。然而,结果永远不会更新以反映视图的更改,例如ngIf和ngFor块的更改。
对于动态查询(static: false),查询解析在@ViewChild()和@ContentChild()的ngAfterViewInit()或ngAfterContentInit()之后进行。结果将根据视图的更改更新,例如ngIf和ngFor块的更改。
使用static: true
的一个不错的用例是,如果您正在使用fromEvent
绑定到模板中定义的元素。请考虑以下模板:
<div [ngStyle]="thumbStyle$ | async" #thumb></div>
如果您不想或不能使用Angular事件绑定,那么您可以在此元素上处理事件,而无需使用订阅或初始化钩子:
@Component({})
export class ThumbComponent {
@ViewChild('thumb', { static: true })
thumb?: ElementRef<HTMLElement>;
readonly thumbStyle$ = defer(() => fromEvent(this.thumb, 'pointerdown').pipe(
switchMap((startEvent) => fromEvent(document, 'pointermove', { passive: true })
));
}
使用defer
很重要。这将确保该observable只有在订阅时才被解析。这会在ngAfterViewInit
被触发之前发生,当async
管道订阅它时发生。由于我们使用了static:true
,所以this.thumb
已经填充好了。
*ngIf
中,并且该块仅在稍后设置为 true,那么我如何获取ViewChild
? - Minh Nghĩa{ static: true }
,但如果在ngOnInit
中没有直接需要访问 ViewChild,则应仅使用{ static: false }
。 - Poul Kruijt