导航在Angular区域之外触发,您是否忘了调用“ ngZone.run()”?

时间:2018-12-06 06:07:05

标签: angular angular-router zonejs

我正在使用Angular 7并遇到问题=>登录成功后,API GET调用成功,并且组件也接收数据,但是UI未显示该数据。

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

  

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

我已经搜索了此警告,并找到了诸如this.ngZone.run()之类的解决方法,并在其中调用了我的API。

但是问题是,我正在使用40多个组件,并且在每个组件中调用了许多API。因此,我必须在每次API调用时都调用ngZone.run(),这似乎很难做到。

请向我建议克服此问题的更好方法。 预先感谢。

  

app.component.ts

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

app.service.ts

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

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

6 个答案:

答案 0 :(得分:10)

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

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

private zone: NgZone

this.zone.run(() => {
                    this.router.navigate(['/login']);
                });

答案 1 :(得分:7)

通常,当您将角度调用包装在与外部Java无关的外部JavaScript回调中时,就会发生这种情况。

示例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()); // now wrapped inside ngZone
  });
}

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

答案 2 :(得分:5)

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

第一种形式:

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");

希望对你有用

答案 3 :(得分:2)

如果我从头开始讲话,则此警告的含义是事件是在区域之外触发的,即如果您知道区域也称为执行上下文,哪个角度是用于更改检测和UI呈现。因此,在进行导航时,角度会期望它重新呈现UI,但是在这里不会发生,这就是您面临的问题。之所以会发出此警告,是因为执行代码时角度处理更改检测和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

答案 4 :(得分:1)

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

constructor(private myService: MyService) {
}

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

@NgModule({
  providers: [
    MyService
  ]

答案 5 :(得分:0)

工作解决方案 - 修复

 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);
      });
    });
  }