为什么即使 *ngIf 设置为 true,@ViewChild 仍然未定义

Jac*_*all 5 angular-ng-if viewchild angular

我遇到了以下问题,该问题已由{static: false}中的属性修复@ViewChild。\n此 stackoverflow Q/A 帮助解决了How should I use the new static option for @ViewChild in Angular 8?

\n

我想更好地理解这个场景以及如何static改变结果,以及变化检测如何影响这个场景。我已经阅读了角度文档中有关更改检测的一些内容,并发现极其缺乏。

\n

我想出了一个 stackblitz 来说明一些我不明白的事情。Stackblitz 角度示例

\n

单击toggle按钮两次时,我在命令行上收到以下内容:

\n
> undefined undefined\n> undefined undefined\n> undefined ElementRef\xc2\xa0{nativeElement: div}\n> undefined ElementRef\xc2\xa0{nativeElement: div}\n\n
Run Code Online (Sandbox Code Playgroud)\n

不过我期望:

\n
> undefined undefined\n> undefined ElementRef\xc2\xa0{nativeElement: div}\n> ElementRef\xc2\xa0{nativeElement: div} ElementRef\xc2\xa0{nativeElement: div}\n> ElementRef\xc2\xa0{nativeElement: div} ElementRef\xc2\xa0{nativeElement: div}\n\n
Run Code Online (Sandbox Code Playgroud)\n

这是代码的逻辑——(请参阅 stackblitz 中的完整代码)

\n
> undefined undefined\n> undefined undefined\n> undefined ElementRef\xc2\xa0{nativeElement: div}\n> undefined ElementRef\xc2\xa0{nativeElement: div}\n\n
Run Code Online (Sandbox Code Playgroud)\n
\n

我的问题是:

\n
    \n
  1. 为什么第二行的值this.falseViewChild显示为未定义。更改检测不应该在设置后运行this.display = false,因此它不应该是未定义的吗?
  2. \n
  3. 为什么this.trueViewChild保持未定义状态。我希望它在*ngIf变为真后找到该元素?
  4. \n
\n

yur*_*zui 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
  } 
}
Run Code Online (Sandbox Code Playgroud)

代码中的顺序如下:

 click
  ||
  \/
someHandler()
  ||
  \/
checkStable()
  ||
  \/
PERFORM CHANGE DETECTION
Run Code Online (Sandbox Code Playgroud)

那么,让我们回答您的问题:

  1. 为什么 this.falseViewChild 的第二行值显示为未定义。设置 this.display = false 后是否应该运行更改检测,因此它不应该是未定义的?

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
} 
Run Code Online (Sandbox Code Playgroud)

这就是为什么您在第一次单击时会得到以下输出:

> undefined undefined
> undefined undefined   <---- nothing has updated

 ......
 update happens here
Run Code Online (Sandbox Code Playgroud)

它稍后会更新,但除非您再次单击,否则您不会看到此内容,因为您稍后不会记录这些值。

  1. Why does this.trueViewChild stay undefined. I would expect it to find the element after the *ngIf becomes true?

因为Angular 文档中有这样的规则:

使用静态查询(static:true),查询在创建视图后、但在更改检测运行之前解析。但是,结果永远不会更新以反映视图的更改,例如 ngIf 和 ngFor 块的更改。

这意味着如果它最初是false(例如,它在 *ngIf 或 内ng-template),那么它将始终是false