提问者:小点点

我应该如何在Angular 8中使用@ViewChild的新静态选项?


我应该如何配置新的角度8视图子?

@ViewChild('searchText', {read: ElementRef, static: false})
public searchTextInput: ElementRef;

VS

@ViewChild('searchText', {read: ElementRef, static: true})
public searchTextInput: ElementRef;

哪一个好些?什么时候应该使用静态:true静态:false


共1个答案

匿名用户

在大多数情况下,您将希望使用{static:false}。这样设置它将确保找到依赖于绑定解析的查询匹配(如结构指令*NGIF等..)。

何时使用statice: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标志,除非您希望使用statice:true选项。

您可以使用angular cling update命令自动升级当前的代码库。

有关迁移指南和更多信息,您可以查看这里和这里

#静态查询和动态查询有什么区别?@viewChild()和@contentChild()查询的静态选项确定查询结果何时可用。

对于静态查询(static:true),查询在视图创建后解析,但在更改检测运行之前解析。但是,结果永远不会更新以反映对视图的更改,例如对ngIf和ngFor块的更改。

对于动态查询(静态:false),查询分别在@ViewChild()和@ContentChild()的ngAfterViewInit()或ngAfterContentInit()之后解析。对于您的视图的更改,如对ngIf和ngFor块的更改,将更新结果。

使用statice:true的一个好用例是使用fromevent绑定到模板中定义的元素。请考虑以下模板:

<div [ngStyle]="thumbStyle$ | async" #thumb></div>

然后,您可以处理该元素上的事件,而不需要使用订阅或init挂钩(如果您不想或不能使用角度事件绑定):

@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管道订阅它时。因为我们使用的是statice:true,所以已经填充了this.thumb