【问题标题】:Angular 7 routerLink directive warning 'Navigation triggered outside Angular zone'Angular 7 routerLink 指令警告“导航在 Angular 区域外触发”
【发布时间】:2019-04-07 13:58:02
【问题描述】:

我正在努力使用 Angular 框架来让我的应用程序顺利运行,但我无法解决路由问题。 我有一个顶级AppComponentapp-routing.module.ts,它们通过我的自定义SlideMenuComponent 管理导航。我的AppComponent的简化html模板:

<app-slide-menu [buttons]="menuButtons"></app-slide-menu>
<router-outlet></router-outlet>

我的SlideMenuComponent有以下html作为核心:

<nav><div *ngFor="let button of buttons">
    <a routerLink="{{button.routerLink}}"
    >{{button.name}}</a>
</div></nav>

用户可以通过此滑动菜单导航到'/courses',该菜单由CoursesComponent 监督,该菜单对指向从服务器检索到的特定CourseComponents 的链接进行分页。这些组件驻留在它们自己的courses.module.ts 模块中以及它们自己的courses-routing.module.ts 中。但是,当我单击任何这些链接时,我会收到Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'? 控制台警告,ngOnInit() 不会被调用为打开的CourseCompontent,并且它不会更新,直到我单击页面上的任何按钮。我在通过router.navigate() 手动导航时遇到了这个问题,通过将此任务转发到NgZone.runTask(router.navigate()) 解决了这个问题,但是为什么anchor 标签和routerLink direcrives 会发生这种情况? 这是我的CoursesComponent 代码摘录:

<nav><ul>
        <li *ngFor="let course of api.data | paginate: {
            currentPage: currentPage, itemsPerPage: limit, totalItems: api.total
        }">
           <a
               [routerLink]="course._id"
               [queryParams]="{ page: '1', limit: '5' }"
           >
            {{course.name}} ({{course.description}})
           </a>
        </li>
</ul></nav>

演示问题的 gif:

【问题讨论】:

  • 你能试试这个代码
  • @Suresh 抱歉,这可能有点误导,但这段代码工作正常,它是我的幻灯片菜单链接,虽然我试图改变它的插值类型,但没有任何有效的改变。当我点击&lt;a [routerLink]="course._id" [queryParams]="{ page: '1', limit: '5' }" &gt; {{course.name}} ({{course.description}}) &lt;/a&gt; 时出现问题
  • RouteLink 应该在 [] 括号中定义。 [routerLink]="[course._id]".
  • @Suresh 尝试过,但没有任何变化。实际上 routerLink 可能只是一个字符串,而不是路径数组
  • @Suresh 是的,我可以使用它作为解决方法,但是为什么会发生这种情况?

标签: angular angular-routing angular-router angular7 angular-routerlink


【解决方案1】:

它发现了一个错误,试试这个作为一种解决方法

constructor(private ngZone: NgZone, private router: Router) {}

public navigate(commands: any[]): void {
    this.ngZone.run(() => this.router.navigate(commands)).then();
}

【讨论】:

  • 工作就像一个魅力,谢谢。此解决方案会出现什么问题?
  • 这给我“ngZone is not defined”
  • @VincentGuyard,将此添加到您的导入中:import { Component, OnInit, ..., NgZone } from '@angular/core';
  • 应用程序中可能有多个组件,我需要将给定的代码放在所有这些组件中吗?
  • 变通方法有效,但感觉像一个黑客,我不知道是什么原因造成的。
【解决方案2】:

当我们在解决方案的某个地方导航时遇到了这个错误。

在我们的侧边栏组件中,我们使用 on-push 更改检测,当路由发生(参数更改)时,我们有一个 this.ref.detectChanges(),它以某种方式破坏了路由(可能将并行运行的解析器踢出 ngZone 或类似的东西)。 将其更改为无论如何首选的this.ref.markForCheck() 后,此错误不再出现。 我很高兴我们不需要解决方法,但奇怪的行为..

希望这对遇到同样问题的人有所帮助。

【讨论】:

    【解决方案3】:

    由于没有公认的答案,而且我发现,使用 Angular 8,排名靠前的答案不太有效,需要更多解释,我有以下补充:

    我的具体问题是 ag-grid,但我怀疑在 *ngFor 或其他地方注入组件的任何地方都可能导致此问题。这与上一个答案非常接近,但改为在导航函数中声明一个字符串参数,然后调用 navigateByUrl 而不是导航。

    import { Component, NgZone } from '@angular/core';
    import { Router } from '@angular/router';
    
    @Component({
      template: `<tag (click)="navigate(path)">clickable text</tag>`
    })
    
    constructor(private ngZone: NgZone, private router: Router) { }
    
    public navigate(path: string): void {
      this.ngZone.run(() => this.router.navigateByUrl(path)).then();
    }
    

    您的里程可能会有所不同,但这对我来说效果很好。

    【讨论】:

    • 我在我的 Ionic 4 (Angular) 应用程序中尝试打开推送通知但没有产生任何结果,仍然抛出相同的警告并卡在主页上,知道吗?
    • @HamletMinjares - 没有想法。你确定你完全遵循这个模式吗? (click) 事件必须调用组件的导航函数,如图所示;它不能再使用 routerLink 了。除此之外,我认为这在 Ionic 中可以正常工作。我不明白为什么会有所作为,但我对 Ioninc 没有太多经验。
    • 我很抱歉;在调用此方法之前,我使用警卫类进行验证,并没有注意到这个警卫在没有 ng 区域的情况下重定向。就在我纠正之后,它就像一个魅力,谢谢!
    • 您的回答帮助我解决了我的问题。尽管使用 angular 10 而不是 8,但效果很好
    【解决方案4】:

    对我来说,这个错误是因为部分代码在 NgZone 之外运行。之后我们运行this.ref.detectChanges() 来检测更改。检测到的更改将更改 DOM 并放入&lt;a [routerLink]="..."&gt;&lt;/a&gt;。这用于中断路由。 解决方案:我们在 NgZone 内部运行 NgZone 之外的部分代码,但使用 this.ngZone.run 。这样我们就不必使用ref.detectChanged(),因为更改的(RxJS 主题订阅)在 NgZone 中。这解决了路由问题。

    希望这对遇到同样问题的人有所帮助。

    【讨论】:

      【解决方案5】:

      工作示例 - 参考这个

       public backButtonSubscription;
            ngAfterViewInit(): void {
              let self = this;
              this.backButtonSubscription = this.platform.backButton.subscribe(() => {
                console.log("back preseed \n \n");
          
                self._ngZone.runOutsideAngular(() => {
                  setTimeout(() => {
                    self.Router.navigateByUrl("/stock-management");
                  }, 100);
                });
              });
            }
      

      【讨论】:

        猜你喜欢
        • 2019-06-24
        • 1970-01-01
        • 2020-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-13
        • 2021-03-30
        • 1970-01-01
        相关资源
        最近更新 更多