对于如下情况,你会在哪里添加重定向逻辑?
flowchart TD
Customer --> ChildRoute["/child"]
ChildRoute --> Condition{Condition?}
Condition -->|是| GrandChildRoute1["/child/grandchild1"]
Condition -->|否| GrandChildRoute2["/child/grandchild2"]
实现方式有很多种。我更倾向于在 Angular@18 中使用 redirectTo 函数,在 child 路由下添加一个专门用于重定向的路由:
export const routes: Routes = [
{
path: "child",
component: ChildComponent,
children: [
{
path: "",
pathMatch: "full",
redirectTo: () => {
const shouldRedirectToChild1 = Math.random() > 0.5;
if (shouldRedirectToChild1) {
return "grandchild1";
}
return "grandchild2";
},
},
{
path: "grandchild1",
loadComponent: () => GrandChild1Component,
},
{
path: "grandchild2",
loadComponent: () => GrandChild2Component,
},
],
},
];
在 Angular@18 之前,我会把该逻辑放在 canActivate 中,像这样:
export const routes: Routes = [
{
path: "child",
component: ChildComponent,
children: [
{
path: "",
pathMatch: "full",
component: ChildComponent,
canActivate: [
() => {
const router = inject(Router);
const shouldRedirectToChild1 = Math.random() > 0.5;
if (shouldRedirectToChild1) {
return router.parseUrl("/child/grandchild1");
}
return router.parseUrl("/child/grandchild2");
},
],
},
{
path: "grandchild1",
loadComponent: () => GrandChild1Component,
},
{
path: "grandchild2",
loadComponent: () => GrandChild2Component,
},
],
},
];
从我的角度来看,这种方式不那么好,原因如下:
canActivate不如redirectTo直观;- 在这种情况下,
canActivate需要component字段才能工作且不报错,但实际上并不需要组件。
还有一种解决方案如下:
export const routes: Routes = [
{
path: "child",
component: ChildComponent,
canActivate: [
(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
const isChildRoute = state.url === "/child";
if (isChildRoute) {
const shouldRedirectToChild1 = Math.random() > 0.5;
if (shouldRedirectToChild1) {
return "grandchild1";
}
return "grandchild2";
}
return true;
},
],
children: [
{
path: "grandchild1",
loadComponent: () => GrandChild1Component,
},
{
path: "grandchild2",
loadComponent: () => GrandChild2Component,
},
],
},
];
这种方式的问题很明显:
- 我们需要判断用户是否直接访问了父级路径,例如:
isChildRoute = state.url === "/child"; - 很容易在这个
canActivate函数中加入其他非重定向相关的逻辑,违反单一职责原则,例如权限相关代码; - 当路由从
/child/grandchild2切换到/child时,由于/child路由已经被激活,上述canActivate将不会被触发。
那么你怎么看?