在大多数情况下,您将使用{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}。
不过要注意,在Angular 9中,{static: false}选项将被设为默认值。这意味着不再需要设置静态标志,除非你想使用static: true选项。
你可以使用angular cli ng update命令自动升级你当前的代码库。
有关迁移指南和更多信息,您可以查看这里和这里
静态查询和动态查询的区别是什么?
@ViewChild()和@ContentChild()查询的静态选项决定查询结果何时可用。
使用静态查询(static: true),查询在视图创建之后,但在更改检测运行之前解析。但是,结果永远不会被更新以反映视图的变化,比如ngIf和ngFor块的变化。
对于动态查询(静态:false),查询分别在@ViewChild()和@ContentChild()的ngAfterViewInit()或ngAfterContentInit()之后解析。当你的视图发生变化时,结果会被更新,比如ngIf和ngFor块的变化。
使用static: true的一个很好的用例是使用fromEvent绑定到模板中定义的元素。考虑下面的模板:
<div [ngStyle]="thumbStyle$ | async" #thumb></div>
然后你可以处理这个元素上的事件,而不需要使用订阅或init钩子(如果你不想或不能使用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 })
// transform to proper positioning
));
}
使用defer很重要。这将确保该可观察对象仅在被订阅时才被解析。这将在ngAfterViewInit被触发之前发生,当异步管道订阅它时。因为我们使用的是static: true, the this。拇指已经被填充了。