在大多数情况下,您会希望使用{static: false}。像这样设置它可以确保找到依赖于绑定解析的查询匹配(如结构指令*ngIf, etc...)。
何时使用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 中的默认后备行为。阅读更多 here 和 here
引入了{ static: true } 选项以支持动态创建嵌入式视图。当您动态创建视图并想要访问TemplateRef 时,您将无法在ngAfterViewInit 中这样做,因为它会导致ExpressionHasChangedAfterChecked 错误。将静态标志设置为 true 将在 ngOnInit 中创建您的视图。
尽管如此:
在大多数其他情况下,最佳做法是使用{static: false}。
请注意,{ static: false } 选项将在 Angular 9 中成为默认选项。这意味着不再需要设置静态标志,除非您想使用 static: true 选项。
您可以使用 angular cli ng update 命令自动升级您当前的代码库。
有关迁移指南以及更多相关信息,您可以查看here 和here
#静态查询和动态查询有什么区别?
@ViewChild() 和 @ContentChild() 查询的静态选项决定查询结果何时可用。
对于静态查询 (static: true),查询会在视图创建后但在更改检测运行之前解析。但是,结果将永远不会更新以反映对视图的更改,例如对 ngIf 和 ngFor 块的更改。
对于动态查询(静态:false),查询分别在 @ViewChild() 和 @ContentChild() 的 ngAfterViewInit() 或 ngAfterContentInit() 之后解析。结果将根据视图的更改进行更新,例如对 ngIf 和 ngFor 块的更改。
使用static: true 的一个很好的用例是,如果您使用fromEvent 绑定到模板中定义的元素。考虑以下模板:
<div [ngStyle]="thumbStyle$ | async" #thumb></div>
然后您可以处理此元素上的事件,而无需使用订阅或初始化挂钩(如果您不想或不能使用角度事件绑定):
@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 很重要。这将确保 observable 仅在订阅时才被解析。这将在ngAfterViewInit 被触发之前发生,此时async 管道订阅它。因为我们使用的是static: true,所以this.thumb 已经被填充了。