为什么在组件内调用detectChanges()不会更新值,但是在setTimeout()中包装代码呢?

kav*_*kav 6 material angular2-changedetection angular

我正在尝试从中选择一组选项中的第一个值 <mat-autocomplete ...>

export class ExampleComponent implements OnInit, AfterViewInit {

@ViewChildren('auto') matAutocomplete: QueryList<any>;

constructor(private cdr: ChangeDetectorRef) { }

ngAfterViewInit() {
    this.foundItemsList.changes.subscribe(options => {
        // ---> This simply works!
        setTimeout(() => this.matAutocomplete.first._keyManager.setFirstItemActive(), 0);

        // ---> This doesn't works?! No error shown, it just seems that the above function isn't called at all. 
        this.matAutocomplete.first._keyManager.setFirstItemActive()
        this.cdr.detectChanges();
    });
}
Run Code Online (Sandbox Code Playgroud)

https://github.com/angular/material2/blob/master/src/lib/autocomplete/autocomplete.ts

AFAIK,detectChanges检查当前组件及其所有子组件的变化检测器是什么,对吗?但似乎它在上面的场景中不起作用.

Sim*_*ver 7

如果您使用的是内容投影 ( ng-content) 或 @HostBindings,请注意。

当您对托管内容的组件运行更改检测或设置主机绑定时,它实际上可能不会生效,因为它是“拥有”这些属性的父组件(甚至可能在不同的模块中)。

但是,与 相关的行为markForCheck()在 2017 年 5 月更改为标记以检查ng-content父组件中的投影。https://github.com/juleskremer/angular/commit/f894dbdd78cf463ed53b6c50d883326ff7fbff87

因此,detectChanges()对于包含的内容似乎是不够的,您应该markForCheck改用它来触发要检查的包含内容。


Gün*_*uer 6

this.cdr.detectChanges()仅运行当前组件(和后代)的更改检测.如果setFirstItemActive()原因在别处发生变化,则不予承保.setTimeout()或者zone.run(...)或者ApplicationRef.tick()导致对整个应用程序运行更改检测,因此涵盖了每个绑定,而不仅仅是当前组件.

  • https://www.google.at/search?q=angular+zone&oq=angular+zone&aqs=chrome.0.0j69i60l3j0l2.1632j0j7&sourceid=chrome&ie=UTF-8.它只是为Angular代码创建了一个新的范围,其中(几乎)修补了所有异步API,以便在异步调用完成时通知Angular. (2认同)
  • @sabithpocker,检查[你还认为Angular中的变更检测需要NgZone(zone.js)吗?](https://blog.angularindepth.com/do-you-still-think-that-ngzone-zone- JS-IS-需要换变化检测功能于角16f7a575afef) (2认同)