import { ActivatedRouteSnapshot , DetachedRouteHandle , RouteReuseStrategy } from '@angular/router' ; import { Injectable } from '@angular/core' ; interface IRouteConfigData { reuse : boolean ; } interface ICachedRoute { handle : DetachedRouteHandle ; data : IRouteConfigData ; } @ Injectable ( ) export class AppReuseStrategy implements RouteReuseStrategy { private static routeCache = new Map < string , ICachedRoute > ( ) ; private static waitDelete : string ; private static currentDelete : string ; /** 进入路由触发，判断是否是同一路由 */ shouldReuseRoute ( future , curr ) { return future . routeConfig === curr . routeConfig ; } /** 表示对所有路由允许复用 如果你有路由不想利用可以在这加一些业务逻辑判断，这里判断是否有data数据判断是否复用 */ shouldDetach ( route ) { const data = this . getRouteData ( route ) ; if ( data ) { return true ; } return false ; } /** 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象 */ store ( route , handle ) { const url = this . getFullRouteUrl ( route ) ; const data = this . getRouteData ( route ) ; if ( AppReuseStrategy . waitDelete && AppReuseStrategy . waitDelete === url ) { AppReuseStrategy . waitDelete = null ; return null ; } else { if ( AppReuseStrategy . currentDelete && AppReuseStrategy . currentDelete === url ) { AppReuseStrategy . currentDelete = null ; return null ; } else { AppReuseStrategy . routeCache . set ( url , { handle , data } ) ; this . addRedirectsRecursively ( route ) ; } } } /** 若 path 在缓存中有的都认为允许还原路由 */ shouldAttach ( route ) { const url = this . getFullRouteUrl ( route ) ; return AppReuseStrategy . routeCache . has ( url ) ; } /** 从缓存中获取快照，若无则返回nul */ retrieve ( route ) { const url = this . getFullRouteUrl ( route ) ; const data = this . getRouteData ( route ) ; return data && AppReuseStrategy . routeCache . has ( url ) ? AppReuseStrategy . routeCache . get ( url ) . handle : null ; } private addRedirectsRecursively ( route ) { const config = route . routeConfig ; if ( config ) { if ( ! config . loadChildren ) { const routeFirstChild = route . firstChild ; const routeFirstChildUrl = routeFirstChild ? this . getRouteUrlPaths ( routeFirstChild ) . join ( '/' ) : '' ; const childConfigs = config . children ; if ( childConfigs ) { const childConfigWithRedirect = childConfigs . find ( c => c . path === '' && ! ! c . redirectTo ) ; if ( childConfigWithRedirect ) { childConfigWithRedirect . redirectTo = routeFirstChildUrl ; } } } route . children . forEach ( childRoute => this . addRedirectsRecursively ( childRoute ) ) ; } } private getFullRouteUrl ( route ) { return this . getFullRouteUrlPaths ( route ) . filter ( Boolean ) . join ( '/' ) . replace ( '/' , '_' ) ; } private getFullRouteUrlPaths ( route ) { const paths = this . getRouteUrlPaths ( route ) ; return route . parent ? [ ... this . getFullRouteUrlPaths ( route . parent ) , ... paths ] : paths ; } private getRouteUrlPaths ( route ) { return route . url . map ( urlSegment => urlSegment . path ) ; } private getRouteData ( route ) { return route . routeConfig && route . routeConfig . data as IRouteConfigData ; } /** 用于删除路由快照*/ public static deleteRouteSnapshot ( url ) { if ( url [ 0 ] === '/' ) { url = url . substring ( 1 ) ; } url = url . replace ( '/' , '_' ) ; if ( AppReuseStrategy . routeCache . has ( url ) ) { AppReuseStrategy . routeCache . delete ( url ) ; AppReuseStrategy . currentDelete = url ; } else { AppReuseStrategy . waitDelete = url ; } } }