我有一个子组件,在其父组件中使用了两次,它使用ngOnChages更新值;
这一切都很好,但是根据通过@Input
变量传递的信息,现在我正在尝试在子级中操作模板。
我发现的是;首次加载父组件时,在函数调用内模板变量未定义
这是有道理的,因为在onChanges
方法中调用了此函数,并且没有给模板足够的加载时间。
我需要重构代码,但是如何?
目前,如果我使用setTimeout
所以简单地:
@ViewChild('myContainer', {read: ElementRef}) myContainer: ElementRef;
@Input() myUpdatingVar
ngOnChanges(): void {
if (this.myUpdatingVar === someValue) {
this.myFunc(this.someValue1);
} else {
this.myFunc(this.someValue2);
}
}
myFunc(param){
do stuff....
this.updateDom(anotherParam);
}
updateDom(param) {
// If I use setTimeout this works
this.myContainer.nativeElement.querySelector(`#someId`); // Undefined
}
答案 0 :(得分:1)
查看本指南:https://angular.io/guide/lifecycle-hooks
角度生命周期事件按特定顺序触发,并且某些事件在dom元素加载之前发生。
ngAfterViewInit是使您知道DOM(或至少您看到的抽象)已准备好进行查询的挂钩。这意味着在触发此事件之前,模板变量和viewchildren等无法正常工作。
编辑: 听起来您了解时间了。为了解决这个问题,我建议在onChanges中使用模板变量之前先检查是否已定义模板变量(现在,它将在以后对onChanges的所有调用中发生),然后如果需要在开始时运行一次,请在ngAfterViewInit中执行相同的操作。
答案 1 :(得分:1)
您可以使用ngOnChanges
来检测更改,而不是使用setter
。
这是您需要做的
@Input()
set myUpdatingVar(value: any) {
if(value) {
this.myFunc(value);
}
}
它不仅会在初始化视图时加载,而且在myUpdatingVar
中进行任何更改时,Angular都会运行setter并执行您的函数。另外,ngOnChanges
是昂贵的生命周期挂钩。如果不小心使用它,它将在组件中发生任何更改时运行。
但是,如果要使用ngOnChanges
,则应使用它在变量中检测到的更改,而不是使用变量本身。
这里是例子
ngOnChanges(changes: SimpleChanges): void {
if (changes.myUpdatingVar.currentValue === someValue) {
this.myFunc(changes.myUpdatingVar.currentValue);
} else {
this.myFunc(changes.myUpdatingVar.currentValue);
}
}
您可以检查是否是第一次更改,还可以获取currentValue
和previousValue
,在这种情况下非常有用。
希望我的回答以某种方式对您有所帮助。 祝您编码愉快!
答案 2 :(得分:1)
使用更新的angular(9.x),我通过将static设置为true解决了这个问题:
@ViewChild('myContainer', {static: true})
答案 3 :(得分:0)
对于DOM操作,您应该使用ngAfterViewInit
生命周期挂钩,以确保模板已加载到DOM中。
ngOnChanges
提前触发一次,甚至在ngOnInit
之前触发。对于DOM操作而言还为时过早。
您可以使用isViewInitialized
布尔值,并在ngAfterViewInit
中将其设置为true,然后在if
中的ngOnChanges
条件下使用它。
答案 4 :(得分:0)
正如其他人所说,onchanges运行太早,无法访问viewchildren,您将需要以下内容:
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
<h2
class="headline"
on="tap:list.toggleClass(class='my-custom-class')">
<ul id="list"></ul>
这样,如果尚未初始化视图,则跳过逻辑,并在初始化视图后手动触发ngOnChanges运行。
所有这一切,除非您正在与一些集成度不佳的第三方库互动,否则可能会有更多角度的方法来实现此目标。