Angular12 路由复用策略规则编写及使用

2021-7-8 Jon angular

1. 路由复用策略服务 route-reuse.service.ts
   ts    107行
import { RouteReuseStrategy, DetachedRouteHandle, ActivatedRouteSnapshot } from '@angular/router';
import { ComponentRef, Injectable } from '@angular/core';

@Injectable()
export class RouteReuseService implements RouteReuseStrategy {
  private handlers: { [key: string]: RootHandler } = {};
  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return this.isDetachable(route);
  }

  store(route: ActivatedRouteSnapshot, handler: DetachedRouteHandle) {
    const storeKey =  this.getStoreKey(route);
    if (handler) {
      // I need to keep track of the time the route is stored so I added storeTime.
      const rootHandler = {
        handle: handler,
        storeTime: +new Date()
      };
      this.handlers[storeKey] = rootHandler;
    }
  }

  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    const storeKey =  this.getStoreKey(route);
    if (this.isAtachable(route, storeKey)) {
      // you can retrun true only
      // clearNewerHandlerOnAttach is optional
      // when load the snapshot (attach old route) I only want to keep routes stored before this route
      // and delete routes stored after this route.
      // for exmaple, if i go to product list and then product detail and then saler information
      // if product list, product detail and saler information are all detachable.
      // when I back from saler information to product detail I don't want to store saler information
      // and when I back from product detail to product list I don't want to store product detail route
      // because I when I go back to product list and then go to the same product detail again
      // I want to load new data. Why?
      // I think people rarely go back and fort 2 pages multiple time
      // by deleting unnecessary stored route we save memory.
      this.clearNewerHandlerOnAttach(this.handlers[storeKey].storeTime);
      return true;
    }
    return false;
  }

  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    const storeKey =  this.getStoreKey(route);
    return this.handlers[storeKey]?.handle;
  }

  shouldReuseRoute( future: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean {
    return future.routeConfig === current.routeConfig;
  }

  private getResolvedUrl(route: ActivatedRouteSnapshot): string {
    return route.pathFromRoot
        .map(v => v.url.map(segment => segment.toString()).join('/'))
        .join('/');
  }

  private getStoreKey(route: ActivatedRouteSnapshot): string {
    const baseUrl = this.getResolvedUrl(route);
    const childrenParts = [];
    let deepestChild = route;
    while (deepestChild.firstChild) {
        deepestChild = deepestChild.firstChild;
        childrenParts.push(deepestChild.url.join('/'));
    }
    return baseUrl + '////' + childrenParts.join('/');
  }

  // true if we mark this route keep:true
  // see it in route config
  private isDetachable(route: ActivatedRouteSnapshot) {
    if ( route?.routeConfig?.data?.keep) {
      return true;
    }
    return false;
  }

  private isAtachable(route: ActivatedRouteSnapshot, storeKey: string) {
    if (this.isDetachable(route) && this.handlers[storeKey]?.handle) {
      return true;
    }
    return false;
  }

  /*
  When the user goes back (attach a root)
  I want to clear newer stored roots.
  */
  private clearNewerHandlerOnAttach(storeTime: number) {
    const handlerKeys = Object.keys(this.handlers);
    handlerKeys.forEach(k => {
      if (this.handlers[k].storeTime > storeTime) {
        const componentRef: ComponentRef<any> = (this.handlers[k].handle as any).componentRef;
        if (componentRef) {
          componentRef.destroy();
        }
        delete this.handlers[k];
      }
    });
  }
}

export interface RootHandler {
  handle: DetachedRouteHandle;
  storeTime: number;
}
2. 使用在路由模块中 app-routing.module.ts
...
import { RouteReuseStrategy, RouterModule, Routes } from '@angular/router';
import { RouteReuseService } from './route-reuse.service';
...
const routes: Routes = [
  ...
  {
    path: 'index',
    data: {keep: true}, // 这里代表需要使用路由复用
    component: IndexComponent
  },
  ...
];
...
@NgModule({
  ...
  providers: [
    /*路由复用策略*/
    { provide: RouteReuseStrategy, useClass: RouteReuseService }
  ]
})

标签: angular router esue

分享这篇文章
赞助鼓励:如果觉得内容对您有所帮助,您可以支付宝(左)或微信(右):

声明:如无特殊注明,所有博客文章版权皆属于作者,转载使用时请注明出处。谢谢!

发表评论:

皖ICP备15010162号-1 ©2015-2020 知向前端
qq:1614245331 邮箱:13515678147@163.com Powered by emlog sitemap