Angular 为什么即使*ngIf设置为true,@ViewChild仍然未定义
我遇到了以下问题,该问题由Angular 为什么即使*ngIf设置为true,@ViewChild仍然未定义,angular,angular-ng-if,viewchild,Angular,Angular Ng If,Viewchild,我遇到了以下问题,该问题由@ViewChild中的{static:false}属性修复。 这个问题有助于解决这个问题 我想更好地理解这个场景,以及静态如何改变结果,以及变化检测如何影响这个场景。我在angular文档中阅读了一些关于变化检测的内容,发现这一点非常缺乏 我想出了一个stackblitz来说明一些我不理解的事情 单击两次toggle按钮时,我会在命令行上看到以下内容: > undefined undefined > undefined undefined > und
@ViewChild
中的{static:false}
属性修复。
这个问题有助于解决这个问题
我想更好地理解这个场景,以及静态
如何改变结果,以及变化检测如何影响这个场景。我在angular文档中阅读了一些关于变化检测的内容,发现这一点非常缺乏
我想出了一个stackblitz来说明一些我不理解的事情
单击两次toggle
按钮时,我会在命令行上看到以下内容:
> undefined undefined
> undefined undefined
> undefined ElementRef {nativeElement: div}
> undefined ElementRef {nativeElement: div}
然而,我预计:
> undefined undefined
> undefined ElementRef {nativeElement: div}
> ElementRef {nativeElement: div} ElementRef {nativeElement: div}
> ElementRef {nativeElement: div} ElementRef {nativeElement: div}
下面是代码的逻辑--(请参阅stackblitz中的完整代码)
@组件({
选择器:“我的应用程序”,
templateUrl:“./app.component.html”,
样式URL:[“/app.component.css”]
})
导出类AppComponent{
@ViewChild(“contentPlaceholder”,{static:true})
trueViewChild:ElementRef;
@ViewChild(“contentPlaceholder”,{static:false})
falseViewChild:ElementRef;
显示=假;
构造函数(){}
show(){
console.log(this.trueViewChild,this.falseViewChild);
this.display=true;
console.log(this.trueViewChild,this.falseViewChild);
}
}
我的问题是:
this.falseViewChild
的第二行值显示为未定义。设置this.display=false
后不应该运行更改检测,因此不应该未定义它this.trueViewChild
保持未定义状态。我希望它在*ngIf
变为true后找到元素角度变化检测在zone.js库的帮助下工作更新ViewChild/内容查询发生在更改检测周期中 js库修补异步API(addEventListener、setTimeout()、Promises…),并准确地知道执行了哪个任务以及任务何时完成 例如,当此任务已完成时,它可以侦听单击事件并发出通知(没有挂起的任务,这意味着区域变得稳定) Angular订阅这些通知,以便从根组件开始对所有三个组件执行更改检测
// your code
(click)="someHandler()"
someHandler() {
....
}
// angular core
checkStable() {
if (there is no any task being executed and there is no any async pending request) {
PERFORM CHANGE DETECTION
}
}
代码中关于的顺序如下所示:
click
||
\/
someHandler()
||
\/
checkStable()
||
\/
PERFORM CHANGE DETECTION
那么,让我们回答您的问题:
显示
属性时没有反应
show() {
console.log(this.trueViewChild, this.falseViewChild);
this.display = true; <--- Angular doesn't do here anything, it only listens to zone state changes
console.log(this.trueViewChild, this.falseViewChild); // nothing should be updated here
// because there wasn't any cd cycle yet
}
show(){
console.log(this.trueViewChild,this.falseViewChild);
this.display=true;未定义未定义
>未定义未定义感谢您的深入回答。问题2现在有意义了。您的分叉堆栈闪电在第一次单击后没有显示任何内容,在第二次单击后仅显示一些内容
。我只是想看看这是否是您的预期效果?是的,您是对的,我查看了不同的行为。第二次单击后,它也应该更新视图。第一个问题仍然有点不清楚。console.log(…)
在this.display=true;
之后未定义,因为Angular尚未从zone.js收到订阅的值,还是因为zone.js没有查看这些更改?此代码在Angular zone内执行,zone知道只有在该处理程序执行Angular checks stat之后才会执行某些操作只有当没有挂起的任务时,它才会发出onMicrotaskEmpty事件。为了运行更改检测循环,已经订阅了此事件这是如何检查区域状态的
> undefined undefined
> undefined undefined <---- nothing has updated
......
update happens here