[英]How should I use the new static option for @ViewChild in Angular 8?
我应该如何配置新的 Angular 8 view child?
@ViewChild('searchText', {read: ElementRef, static: false})
public searchTextInput: ElementRef;
对比
@ViewChild('searchText', {read: ElementRef, static: true})
public searchTextInput: ElementRef;
哪个更好? 我什么时候应该使用static:true
与static:false
?
在大多数情况下,您会想要使用{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 中的默认后备行为。在此处和此处阅读更多信息
引入了{ static: true }
选项以支持动态创建嵌入式视图。 当您动态创建视图并想要访问TemplateRef
时,您将无法在ngAfterViewInit
中这样做,因为它会导致ExpressionHasChangedAfterChecked
错误。 将静态标志设置为 true 将在 ngOnInit 中创建您的视图。
尽管如此:
在大多数其他情况下,最佳实践是使用
{static: false}
。
请注意,尽管{ static: false }
选项将在 Angular 9 中成为默认选项。这意味着不再需要设置 static 标志,除非您想使用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>
然后,您可以处理此元素上的事件,而无需使用订阅或初始化挂钩(如果您不想或不能使用角度事件绑定):
@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
已经被填充了。
因此,根据经验,您可以选择以下内容:
{ static: true }
当你想访问ViewChild
中的ngOnInit
时需要设置。
{ static: false }
只能在ngAfterViewInit
中访问。 当您在模板中的元素上有一个结构指令(即*ngIf
)时,这也是您想要的。
从角度文档
static - 是否在更改检测运行之前解析查询结果(即仅返回静态结果)。 如果未提供此选项,编译器将退回到其默认行为,即使用查询结果来确定查询解析的时间。 如果任何查询结果在嵌套视图中(例如 *ngIf),则查询将在更改检测运行后解析。 否则,它将在更改检测运行之前解决。
如果孩子不依赖任何条件,使用static:true
可能是一个更好的主意。 如果元素的可见性发生变化,那么static:false
可能会给出更好的结果。
PS:由于它是一项新功能,我们可能需要运行性能基准测试。
正如@Massimiliano Sartoretto 所提到的, github 提交可能会给你更多的见解。
来到这里是因为在升级到 Angular 8 后, ngOnInit 中的 ViewChild 为空。
静态查询在 ngOnInit 之前填充,而动态查询(静态:false)在之后填充。 换句话说,如果在你设置 static:false 之后 viewchild 现在在 ngOnInit 中为 null,你应该考虑更改为 static:true 或将代码移动到 ngAfterViewInit。
见https://github.com/angular/angular/blob/master/packages/core/src/view/view.ts#L332-L336
其他答案是正确的,并解释了为什么会出现这种情况:依赖于结构指令的查询,例如 ngIf 中的 ViewChild 引用,应该在该指令的条件已解决后运行,即在更改检测后运行。 但是,可以安全地使用 static: true ,从而在 ngOnInit 之前解析未嵌套引用的查询。 恕我直言,这个特殊情况值得一提,因为空异常可能是您遇到这种特殊性的第一种方式,就像对我一样。
查看子 @angular 5+ 标记两个参数('本地引用名称',静态:false|true)
@ViewChild('nameInput', { static: false }) nameInputRef: ElementRef;
要知道真假之间的区别检查这个
static - 是否在更改检测运行之前解析查询结果(即仅返回静态结果)。 如果未提供此选项,编译器将退回到其默认行为,即使用查询结果来确定查询解析的时间。 如果任何查询结果在嵌套视图中(例如 *ngIf),则查询将在更改检测运行后解析。 否则,它将在更改检测运行之前解决。
在 ng8 中,您可以手动设置何时访问父组件中的子组件。 当你设置 static 为 true 时,意味着父组件只在onInit
钩子中获取组件的定义:例如:
// You got a childComponent which has a ngIf/for tag
ngOnInit(){
console.log(this.childComponent);
}
ngAfterViewInit(){
console.log(this.childComponent);
}
如果 static 为 false ,那么您只能在 ngAfterViewInit() 中获得定义,在 ngOnInit() 中,您将获得未定义。
查看孩子
...可以将其用于模板元素引用。
...对于特定组件参考之外。
使用装饰器样式语法.. @ViewChild( selector) reference : ElementRef || QueryList.
@ViewChild( selector) reference : ElementRef || QueryList.
特定组件或元素的引用。
在AfterViewInIt()
中使用它。
我们可以在Oninit()
中使用它。
但这特定于使用ngAfterViewInit()
。
最后{static : false}
应该放在@ViewChild( Useme , { static : false})
... 以供模板变量引用。
模板文件中的变量看起来像。 #Useme
。
静态属性告知 Angular 我们孩子的可用性
例如:如果 static 设置为true ,我们通知 Angular 我们的孩子从一开始就在页面上可用(这意味着它不依赖于 *ngIf、页面绑定、API 调用等)所以 Angular 在最早的生命周期中寻找它钩子(ngOnInit)并且不再寻找它
如果我们将 static 设置为false ,我们会通知 angular 我们的孩子依赖于一些条件指令,因此 angular 会在每个更改检测周期后尝试寻找我们的孩子,如果它可用,我们可以在 ngAfterViewInit() 生命周期钩子中访问它
我应该如何配置新的Angular 8视图子级?
@ViewChild('searchText', {read: ElementRef, static: false})
public searchTextInput: ElementRef;
与
@ViewChild('searchText', {read: ElementRef, static: true})
public searchTextInput: ElementRef;
哪个更好? 什么时候应该使用static:true
vs static:false
?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.