Angular 4 - 没有启动斜杠的routerLinks在未被捕获的错误后被重写

时间:2017-05-10 10:29:52

标签: javascript angular navigation angular-ui-router

这是Angular 4 + zonejs: routing stops working after uncaught error的后续行动 因为我们很难将建议的更改整合到我们的项目中。

可以在app.html中的这个改编的plunker https://embed.plnkr.co/oUE71KJEk0f1emUuMBp8/中看到这个原因:

我们项目中的routerLinks没有斜杠" /"前缀。 一旦您在访问"错误组件"后导航到另一个部分,这将打破整个导航。 所有链接都用当前路径重写,例如家。

在routerLink属性中添加斜杠可以修复此行为。

为什么?

是否有关于此的文档/规范?

我们只找到了这个angular ticketapi for RouterLink-directive来说

  

或者不以斜线开头,路由器将查找当前激活路线的子节点。

但是,这与前一个问题中建议的解决方法分别与未被捕获的错误有何关系?

1 个答案:

答案 0 :(得分:1)

发生导航错误后,路由状态将恢复

this.currentRouterState = storedState;
this.currentUrlTree = storedUrl;

https://github.com/angular/angular/blob/4.1.2/packages/router/src/router.ts#L750-L751

在执行createUrlTree之后,获得了startPosition:

function findStartingPosition(nav, tree, route) {
    if (nav.isAbsolute) { // it will be executed when you use `/` in routeLink
        return new Position(tree.root, true, 0);
    }
    if (route.snapshot._lastPathIndex === -1) { // without '/'
        return new Position(route.snapshot._urlSegment, true, 0);
    }
    ...
}

正如我们在上面的代码中看到的那样,当您在routeLinks中使用斜杠时,路由器将根据tree.root创建未发生变化的位置。

然后它用于在下面的代码中创建UrlTreeoldSegmentGroup

function tree(oldSegmentGroup, newSegmentGroup, urlTree, queryParams, fragment) {
    ...
    if (urlTree.root === oldSegmentGroup) { // will be false after the error
        return new UrlTree(newSegmentGroup, qp, fragment);
    }
    return new UrlTree(replaceSegment(urlTree.root, oldSegmentGroup, newSegmentGroup), qp, fragment);
}

因此,解决方法可能如下:

我们不再需要RouteReuseStrategy

我们存储错误状态

let erroredUrlTree;
let erroredState;

export class AppModule {
  constructor(private router: Router) {
    router.events.subscribe(function (e) {
      if(e instanceof  NavigationError ) {
        erroredState = (router as any).currentRouterState;
        erroredUrlTree =  (router as any).currentUrlTree;
      }
    });
  }
}

并在发生错误后恢复它:

@Injectable()
export class MyErrorHandler implements ErrorHandler {
  constructor(private inj: Injector) {}

  handleError(error: any): void {
    console.log('MyErrorHandler: ' + error);
    if(erroredUrlTree) {
      let router: any = this.inj.get(Router);
      router.currentRouterState = erroredState;
      router.currentUrlTree = erroredUrlTree;
      erroredState = null;
      erroredUrlTree = null;
    }
  }
}

<强> Modified Plunker

看起来很糟糕,但也许有助于理解问题是什么