如何将具有某些 id 的路由重定向到人类友好的 url 并处理 angular 路由中的规范 url?
How to redirect the route with some id to human friendly url and handle canonical url in angular routes?
我有两个url格式
example.com/posts/:postId
和example.com/posts/:postId/:postTitle
就像stack-overflow个人问题url一样。
在angular路由中,我需要将所有带有:postId
的url重定向到:postId/:PostTitle
,或者直接加载带有:postId/:PostTitle
的页面到相同的页。
post.module.ts
const routes: Routes = [
{
path: ':postId',
resolve: {data: PdResolver},
redirectTo: ':postId/:PostTitle',
pathMatch: 'full'
},
{
path: ':postId/:PostTitle',
component: PostComponent,
data: {
title: 'This has to be the post fetched title'
}
}
];
redirectTo: ':postId/:PostTitle'
:这里我没有 postTitle 所以它抛出错误
- 如何将 postTitle 附加到 url 并避免重复
url 问题。
- 遵循此模式的最佳做法是什么。
I don't have the title so first I need to get postTitle using the
postId, so we have a post data resolver (PdResolver),
问题更新:解决方法:
我尝试使用 child 组件,它至少解决了这个问题,但仍然想知道这是否是我应该遵循的方法。
{
path: ':postId',
component: PostOutletComponent,
resolve: {data: PdResolver},
children: [
{
path: ':postTitle',
component: PostComponent,
}]
}
在 PostOutletComponent
中,我在获取标题后进一步导航到 child 组件
PostOutletComponent.ts
static stripHtml(html: string) {
let div = document.createElement('DIV');
div.innerHTML = html;
const cleanText = div.innerText;
div = null;
return cleanText;
}
ngOnInit() {
this.reolveData = this._route.snapshot.data;
let postTitle = PostOutletComponent.stripHtml(
this.reolveData.data.data.post_title);
postTitle = postTitle.replace(/\s+/g, '-').toLowerCase();
this.router.navigate([postTitle], {relativeTo: this._route});
}
我根据你的代码做了一个 Stackblitz:https://stackblitz.com/edit/angular-r1tvx2
它解决了如果用户导航到具有现有 ID 但标题错误的 URL 时出现的问题。在上面的示例中,标题被更正为 Stack Overflow。
我只使用了一个解析器和一个组件 class。解析器负责重定向到正确的 URL。请注意,Resolver 放置在具有标题的更具体的路由中。
路由配置,路由的顺序很重要,先到标题更具体的路由:
{
path: "posts/:id/:title",
component: PostComponent,
resolve: { somedata: PostDetailResolverService }
},
{
path: "posts/:id",
redirectTo: "posts/:id/title-to-be-repalced",
},
{ path: "**", component: PageNotFoundComponent }
];
解析器,重定向到具有正确标题的 URL:
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<Somedata> | Observable<never> {
let id = +route.paramMap.get("id");
let title = route.paramMap.get("title");
return this.getData(id).pipe(
take(1),
mergeMap(res => {
if (res) {
console.log("Resolver - Navigation continues to the route with data:", res);
if (!title || title != res.title) {
this.router.navigate(["posts/" + res.id + "/" + res.title]);
}
return of(res);
} else {
// id not found
console.log("Navigation cancelled");
this.router.navigate([""]);
return EMPTY;
}
})
);
}
我有两个url格式
example.com/posts/:postId
和example.com/posts/:postId/:postTitle
就像stack-overflow个人问题url一样。
在angular路由中,我需要将所有带有:postId
的url重定向到:postId/:PostTitle
,或者直接加载带有:postId/:PostTitle
的页面到相同的页。
post.module.ts
const routes: Routes = [
{
path: ':postId',
resolve: {data: PdResolver},
redirectTo: ':postId/:PostTitle',
pathMatch: 'full'
},
{
path: ':postId/:PostTitle',
component: PostComponent,
data: {
title: 'This has to be the post fetched title'
}
}
];
redirectTo: ':postId/:PostTitle'
:这里我没有 postTitle 所以它抛出错误- 如何将 postTitle 附加到 url 并避免重复 url 问题。
- 遵循此模式的最佳做法是什么。
I don't have the title so first I need to get postTitle using the postId, so we have a post data resolver (PdResolver),
问题更新:解决方法:
我尝试使用 child 组件,它至少解决了这个问题,但仍然想知道这是否是我应该遵循的方法。
{
path: ':postId',
component: PostOutletComponent,
resolve: {data: PdResolver},
children: [
{
path: ':postTitle',
component: PostComponent,
}]
}
在 PostOutletComponent
中,我在获取标题后进一步导航到 child 组件
PostOutletComponent.ts
static stripHtml(html: string) {
let div = document.createElement('DIV');
div.innerHTML = html;
const cleanText = div.innerText;
div = null;
return cleanText;
}
ngOnInit() {
this.reolveData = this._route.snapshot.data;
let postTitle = PostOutletComponent.stripHtml(
this.reolveData.data.data.post_title);
postTitle = postTitle.replace(/\s+/g, '-').toLowerCase();
this.router.navigate([postTitle], {relativeTo: this._route});
}
我根据你的代码做了一个 Stackblitz:https://stackblitz.com/edit/angular-r1tvx2
它解决了如果用户导航到具有现有 ID 但标题错误的 URL 时出现的问题。在上面的示例中,标题被更正为 Stack Overflow。
我只使用了一个解析器和一个组件 class。解析器负责重定向到正确的 URL。请注意,Resolver 放置在具有标题的更具体的路由中。
路由配置,路由的顺序很重要,先到标题更具体的路由:
{
path: "posts/:id/:title",
component: PostComponent,
resolve: { somedata: PostDetailResolverService }
},
{
path: "posts/:id",
redirectTo: "posts/:id/title-to-be-repalced",
},
{ path: "**", component: PageNotFoundComponent }
];
解析器,重定向到具有正确标题的 URL:
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<Somedata> | Observable<never> {
let id = +route.paramMap.get("id");
let title = route.paramMap.get("title");
return this.getData(id).pipe(
take(1),
mergeMap(res => {
if (res) {
console.log("Resolver - Navigation continues to the route with data:", res);
if (!title || title != res.title) {
this.router.navigate(["posts/" + res.id + "/" + res.title]);
}
return of(res);
} else {
// id not found
console.log("Navigation cancelled");
this.router.navigate([""]);
return EMPTY;
}
})
);
}