Angular 4 - 没有启动斜杠的routerLinks在未被捕获的错误后被重写 [英] Angular 4 - routerLinks without starting slash get rewritten after uncaught error
问题描述
以下是 Angular 4 + zonejs:路由在未捕获的错误后停止工作
,因为我们有一个很难将建议的更改整合到我们的项目中。
这个原因可以在这个改编的plunker中看到 https://embed.plnkr.co/oUE71KJEk0f1emUuMBp8/ :
routerLinks in我们的项目没有斜杠/前缀。
一旦您在访问错误组件后导航到另一个部分,这将打破整个导航。
所有链接都是用当前路径重写的,例如:回家路线链接属性中的斜杠修复了这种行为。
为什么会这样?
是否有关于此的文档/规范?
我们只发现了这个角票和对于RouterLink指令的api ,
或者不以斜杠开头,路由器会查找当前激活路径的子节点。
但这与上一个问题中建议的解决方法分别与未被捕获的错误有什么关系?
发生导航错误后,恢复路由状态
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){//它将在你使用时执行routeLink
中的`/`返回新位置(tree.root,true,0);
}
if(route.snapshot._lastPathIndex === -1){//没有'/'
返回新位置(route.snapshot._urlSegment,true,0);
}
...
}
我们可以看到在上面的代码中,当您在routeLinks中使用斜杠时,路由器将根据 tree.root
创建未经更改的位置。
然后它用于在下面的代码中创建 UrlTree
( oldSegmentGroup
)
函数树(oldSegmentGroup,newSegmentGroup,urlTree,queryParams,fragment){
...
if(urlTree.root === oldSegmentGroup) {//在错误
返回新的UrlTree(newSegmentGroup,qp,fragment)之后将为false;
}
返回新的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()
导出类MyErrorHandler实现ErrorHandler {
构造函数(private inj:Injector){}
handleError(错误:任何):void {
console.log('MyErrorHandler:'+ error);
if(erroredUrlTree){
let router:any = this.inj.get(Router);
router.currentRouterState = erroredState;
router.currentUrlTree = erroredUrlTree;
erroredState = null;
erroredUrlTree = null;
}
}
}
看起来很糟糕但也许它有助于理解问题是什么
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.
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.
Adding the slash in the routerLink attributes fixes this behaviour.
Why is that?
And is there some documentation/spec concerning this?
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
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);
}
...
}
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.
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:
We no longer need RouteReuseStrategy
.
We store errored state
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;
}
});
}
}
and recovery it after error occurs:
@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屋!