Angular 中跨分模块后路由复用问题

当我们的 Angular 应用越来越大后,就需要考虑使用模块或者直接使用库来将解体应用,使用时进来懒加载,加快访问速度。当跨分模块后,普通的路由复用策略就是失效,需要额外的解决方法。

前提

angular 使用路由复用 这篇文章里介绍了如何使用路由复用。

angular 划分库 这篇文章里介绍了如何使用库的方式来减小应用复杂性。

问题

使用懒加载后,应用大概率会抛出 Cannot reattach ActivatedRouteSnapshot created from a different route 这个错误,这主要是因为,使用模块后,每个模块都可能会有 '' 这个路径来做默认路由,系统无法正确找到路由快照。

解决

解决方法也比较简单,既然是因为 key 重复,那就使用不会重复的名称来作为 key 就行。我这边的解决方案,是去定义一个自定义的结构来存储数据,Route 类型中提供了属性data,就是下面代码里的 data

const routes: Routes = [
{
    path: 'login',
    component: LoginComponent,
    data: { url: '/login' },
  },
];

复用策略中也使用 data 中的 url来实现快照的存储和还原。

import { RouteReuseStrategy, , ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router';

export class AppRouteReuseStrategy implements RouteReuseStrategy {
  public static handlers: Map<string, DetachedRouteHandle | undefined> = new Map();

  constructor() { }

  public shouldDetach(_route: ActivatedRouteSnapshot): boolean {
    return true;
  }

  public store(
    route: ActivatedRouteSnapshot,
    handle: DetachedRouteHandle
  ): void {
    if (!route.data) return;
    AppRouteReuseStrategy.handlers.set(route.data['url'], handle);
  }

  public shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return !!route.routeConfig && !!AppRouteReuseStrategy.handlers.get(route.data['url']);
  }

  public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null {
    if (!route.data || !AppRouteReuseStrategy.handlers.has(route.data['url'])) return null;
    return AppRouteReuseStrategy.handlers.get(route.data['url'])!;
  }

  public shouldReuseRoute(
    future: ActivatedRouteSnapshot,
    curr: ActivatedRouteSnapshot
  ): boolean {
    return future.routeConfig === curr.routeConfig;
  }
}
发布时间:2022-09-05