Angular 4 - 没有开始斜线的 routerLinks 在未捕获的错误后被重写 [英] Angular 4 - routerLinks without starting slash get rewritten after uncaught error
问题描述
这是对 Angular 4 + zonejs:路由在未捕获错误后停止工作的跟进因为我们很难将建议的更改集成到我们的项目中.
This is a follow up to Angular 4 + zonejs: routing stops working after uncaught error since we had a hard time integration the suggested changes into our project.
这个原因可以在这个改编的plunker中看到https://embed.plnkr.co/oUE71KJEk0f1emUuMBp8/ 在 app.html 中:
The reason for this can be seen in this adapted plunker https://embed.plnkr.co/oUE71KJEk0f1emUuMBp8/ in app.html:
我们项目中的路由器链接没有以斜杠/"为前缀.一旦您在访问错误组件"后导航到另一个部分,这会破坏整个导航.所有链接都用当前路径重写,例如家.
The routerLinks in our project were not prefixed with a slash "/". This breaks the whole navigation once you navigate to another section after visiting the "Error Component". All links are being rewritten with the current path, e.g. home.
在 routerLink 属性中添加斜杠可修复此行为.
Adding the slash in the routerLink attributes fixes this behaviour.
这是为什么?
是否有一些关于此的文档/规范?
我们只找到了这个 angular 票 和 用于RouterLink-directive的api,它说
We only found this angular ticket and the api for RouterLink-directive which says
或者不以斜线开头,路由器将查看当前激活路由的子节点.
or doesn't begin with a slash, the router will instead look in the children of the current activated route.
但这与上一个问题中建议的解决方法分别与未捕获错误发生的情况有何关系?
But how is this related to what is happening with an uncaught error respectively with the suggested workaround from the previous question?
推荐答案
发生导航错误后路由状态恢复
After an navigation error happens the routing state is restored
this.currentRouterState = storedState;
this.currentUrlTree = storedUrl;
https:///github.com/angular/angular/blob/4.1.2/packages/router/src/router.ts#L750-L751
之后在执行 createUrlTree
后,得到 startPosition:
After that within executing createUrlTree
the startPosition is obtained:
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
创建位置.
As we can see in code above when you use slash in routeLinks then router will create position based on tree.root
which has not changed.
然后用于创建UrlTree
(下面代码中的oldSegmentGroup
)
then it is used for creating UrlTree
(oldSegmentGroup
in code below)
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);
}
因此解决方法可能如下:
So workaround might be as follows:
我们不再需要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;
}
}
}
看起来很糟糕,但也许有助于了解问题所在
It looks terrible but maybe it will help to understand what the problem is
这篇关于Angular 4 - 没有开始斜线的 routerLinks 在未捕获的错误后被重写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!