106

我正在使用 Angular 7 并面临一个问题 => 在成功登录 API GET 调用并且组件也接收数据后,但 UI 没有显示该数据。

当我打开浏览器控制台时,数据会立即填充到 UI 上,并且控制台中会显示警告。

“core.js:15686 导航在 Angular 区域外触发,您是否忘记调用 'ngZone.run()'?”

我用谷歌搜索了这个警告并找到了一些解决方法,比如在其中this.ngZone.run()调用我的 API。

但问题是,我使用了 40 多个组件并在每个组件中调用了如此多的 API。所以我必须调用ngZone.run()每个 API 调用,这似乎很难做到。

请建议我更好的方法来克服这个问题。提前致谢。

app.component.ts

getEmployees(): void {
    this.employeeService.getEmployees().subscribe(e => {
        this.employees = e;
    });
}

应用服务.ts

@Injectable()
export class EmployeeService {
    constructor(private httpClient: HttpClient) { }

    getEmployees() {
        return this.httpClient.get<EmployeeModel[]>('employees');
    }
4

6 回答 6

111

通常,当您将来自与 Angular 代码无关的外部 JavaScript 的 Angular 调用包装在一些外部 js 回调中时,就会发生这种情况。

示例app.component.ts

callMyCustomJsLibrary() {
  googleSdk.getLocations(location => this.getEmployees());
}

getEmployees(): void {
    this.employeeService.getEmployees().subscribe(e => {
        this.employees = e;
    });
}

在这种情况下,您必须将调用包含在 NgZone 中,例如: this.ngZone.run(() => this.getEmployees());

然后app.component.ts将如下所示:

callMyCustomJsLibrary() {
  googleSdk.getLocations(location => this.ngZone.run(() => this.getEmployees()));
}

getEmployees(): void {
    this.employeeService.getEmployees().subscribe(e => {
        this.employees = e;
    });
}
于 2019-03-10T11:52:45.143 回答
47

通过将路由器导航命令包装在 ngZone 中解决了我的问题。请检查下面的代码

在构造函数中添加“私有区域:NgZone”。

private zone: NgZone

this.zone.run(() => {
                    this.router.navigate(['/login']);
                });
于 2020-10-07T20:15:17.107 回答
14

如果我从顶部说话,那么此警告的含义是事件在区域外触发。Angular 使用区域,也称为更改检测和 UI 呈现执行上下文。因此,在导航时,Angular 期望重新渲染 UI,但这里没有发生。这就是你面临的问题。所以它会抛出这个警告,因为当执行的代码位于 Angular 区域内时,Angular 正在处理更改检测和 UI 渲染。

但实际上,当您尝试在subscribe方法中调用路由器导航时,就会出现此警告。

如果您将路由器导航调用置于方法之外,subscribe则它不会再次抛出此警告,并且您将在导航后看到预期的 UI。

有关区域的更多信息,请阅读并观看下面提到的视频:

https://blog.thoughtram.io/angular/2017/02/21/using-zones-in-angular-for-better-performance.html#running-outside-angulars-zone

https://www.youtube.com/watch?v=3IqtmUscE_U&t=150

于 2019-03-21T16:47:05.800 回答
10

我有同样的问题。这对我有用,你有两种方法:

第一种形式:

document.location.href=`/component/${param}/...`

这样做的问题是它会重新加载整个应用程序,这会使其变慢

第二种方法:

导入这个

import { Router } from '@angular/router';
import { Component, NgZone } from '@angular/core';

构造函数:

 constructor(private _ngZone: NgZone, private _router: Router) { }


  goTo(comp, param){
    this._ngZone.run(()=>{
    this._router.navigate([comp, param])
    });
  }

因此,当您想要访问您的组件时,只需:

this.goTo("/myComponent", "my-param-value");

我希望这个对你有用

于 2021-03-02T23:23:18.713 回答
0

工作解决方案 - FIX

 ngAfterViewInit(): void {
    let self = this;
      this.platform.backButton.subscribe(() => {
      console.log("back preseed \n \n");

      self._ngZone.runOutsideAngular(() => {
        setTimeout(() => {
          self.Router.navigateByUrl("/stock-management");
        }, 100);
      });
    });
  }
于 2021-07-16T20:50:11.273 回答
-8

如果您尝试注入定制服务,则会发生这种情况:

constructor(private myService: MyService) {
}

当您忘记在模块配置中提供它时:

@NgModule({
  providers: [
    MyService
  ]
于 2019-04-17T07:21:25.250 回答