我应该如何在 Angular 8 中为 @ViewChild 使用新的静态选项? [英] How should I use the new static option for @ViewChild in Angular 8?

查看:35
本文介绍了我应该如何在 Angular 8 中为 @ViewChild 使用新的静态选项?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我应该如何配置新的 Angular 8 视图子项?

@ViewChild('searchText', {read: ElementRef, static: false})公共搜索文本输入:ElementRef;

对比

@ViewChild('searchText', {read: ElementRef, static: true})公共搜索文本输入:ElementRef;

哪个更好?我什么时候应该使用 static:truestatic:false?

解决方案

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

何时使用 static: false 的示例:

@Component({模板:`<div *ngIf="showMe";#viewMe>我在吗?</div><按钮(点击)=showMe = !showMe"></button>`})导出类 ExampleComponent {@ViewChild('viewMe', { static: false })viewMe?: ElementRef;showMe = 假;}

static: false 将成为 Angular 9 中的默认回退行为.阅读更多 这里这里

引入了 { static: true } 选项以支持动态创建嵌入式视图.当您动态创建视图并希望访问 TemplateRef 时,您将无法在 ngAfterViewInit 中这样做,因为它会导致 ExpressionHasChangedAfterChecked错误.将静态标志设置为 true 将在 ngOnInit 中创建您的视图.

尽管如此:

<块引用>

在大多数其他情况下,最佳实践是使用 {static: false}.

请注意,{ static: false } 选项将在 Angular 9 中成为默认选项.这意味着不再需要设置静态标志,除非您想使用 静态:true 选项.

您可以使用 angular cli ng update 命令自动升级您当前的代码库.

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

<块引用>

#静态查询和动态查询的区别是什么?@ViewChild() 和 @ContentChild() 查询的静态选项决定了查询结果何时可用.

<块引用>

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

<块引用>

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


使用 static: true 的一个很好的用例是,如果您使用 fromEvent 绑定到模板中定义的元素.考虑以下模板:

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

然后您可以在不需要使用订阅或初始化钩子的情况下处理此元素上的事件(如果您不想或不能使用角度事件绑定):

@Component({})导出类 ThumbComponent {@ViewChild('thumb', { static: true })拇指?:ElementRef;readonly thumbStyle$ = defer(() => fromEvent(this.thumb, 'pointerdown').pipe(switchMap((startEvent) => fromEvent(document, 'pointermove', {passive: true })//转换到正确的位置));}

使用defer很重要.这将确保 observable 仅在订阅时解析.这将在 ngAfterViewInit 被触发之前发生,当 async 管道订阅它时.因为我们使用的是 static: truethis.thumb 已经被填充了.

How should I configure the new Angular 8 view child?

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

vs

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

Which is better? When should I use static:true vs static:false?

解决方案

In most cases you will want to use {static: false}. Setting it like this will ensure query matches that are dependent on binding resolution (like structural directives *ngIf, etc...) will be found.

Example of when to use 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;
}

The static: false is going to be the default fallback behaviour in Angular 9. Read more here and here

The { static: true } option was introduced to support creating embedded views on the fly. When you are creating a view dynamically and want to acces the TemplateRef, you won't be able to do so in ngAfterViewInit as it will cause a ExpressionHasChangedAfterChecked error. Setting the static flag to true will create your view in ngOnInit.

Nevertheless:

In most other cases, the best practice is to use {static: false}.

Be aware though that the { static: false } option will be made default in Angular 9. Which means that setting the static flag is no longer necessary, unless you want to use the static: true option.

You can use the angular cli ng update command to automatically upgrade your current code base.

For a migration guide and even more information about this, you can check here and here

#What is the difference between static and dynamic queries? The static option for @ViewChild() and @ContentChild() queries determines when the query results become available.

With static queries (static: true), the query resolves once the view has been created, but before change detection runs. The result, though, will never be updated to reflect changes to your view, such as changes to ngIf and ngFor blocks.

With dynamic queries (static: false), the query resolves after either ngAfterViewInit() or ngAfterContentInit() for @ViewChild() and @ContentChild() respectively. The result will be updated for changes to your view, such as changes to ngIf and ngFor blocks.


A nice use-case for using static: true, is if you are using fromEvent to bind to an element defined in the template. Consider the following template:

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

You can then handle events on this element without the need of using subscriptions or init hooks (if you don't want to or cannot use angular event binding):

@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
  ));
}

It is important to use defer. This will make sure the observable is only resolved when it's subscribed to. This will happen before the ngAfterViewInit gets triggered, when the async pipe subscribes to it. Because we are using static: true, the this.thumb is already populated.

这篇关于我应该如何在 Angular 8 中为 @ViewChild 使用新的静态选项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆