我遇到了以下问题,该问题已由{static: false}
中的@ViewChild
属性修复。
这个How should I use the new static option for @ViewChild in Angular 8?有助于解决堆栈溢出问题。
我想更好地了解这种情况,以及static
如何改变结果以及变化检测如何影响这种情况。我已经在角度文档中读到了一些有关变化检测的内容,发现它非常缺乏。
我想出了一个堆炸弹,它说明了我不理解的东西。 Stackblitz angular example
两次单击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中的完整代码)
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
@ViewChild("contentPlaceholder", { static: true })
trueViewChild: ElementRef;
@ViewChild("contentPlaceholder", { static: false })
falseViewChild: ElementRef;
display = false;
constructor() {}
show() {
console.log(this.trueViewChild, this.falseViewChild);
this.display = true;
console.log(this.trueViewChild, this.falseViewChild);
}
}
我的问题是:
this.falseViewChild
的第二行值显示为undefined。设置this.display = false
之后是否应该不进行更改检测,因此不应将其不确定?this.trueViewChild
保持未定义状态。我希望它在*ngIf
变为true之后找到元素?答案 0 :(得分:1)
角度变化检测借助zone.js库工作。 更新ViewChild / Content查询发生在更改检测周期内。
zone.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
所以,让我们回答您的问题:
更改display
属性时没有反应
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
}
这就是为什么您在第一次单击时获得以下输出的原因:
> undefined undefined
> undefined undefined <---- nothing has updated
......
update happens here
它将在以后进行更新,但是除非再次单击,否则您将看不到它,因为以后不会记录这些值。
Why does this.trueViewChild stay undefined. I would expect it to find the element after the *ngIf becomes true?
因为Angular documentation中有此规则:
对于静态查询(static:true),查询会在视图一次解析 已创建,但在运行更改检测之前。结果, 但是,将永远不会更新以反映对视图的更改,例如 更改为ngIf和ngFor块。
这意味着,如果最初是false
(例如,它位于* ngIf或ng-template
内),则它将始终为false