解决angular路由复用懒加载不起作用的问题
2019-01-16 本文已影响176人
krock01
路由复用
路由复用主要是为了缓存一些页面的状态,例如:搜索结果,查看某一条后再回到页面依然保持原有的搜索列表结果。
非懒加载路由
即直接路由组件
path: "",
component: LayoutComponent,
children: [
{
path: "menu",
component: MenuComponent
},
{
path: "user",
component: UserComponent
}
]
非懒加载的路由策略重写
import { RouteReuseStrategy, DefaultUrlSerializer, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router';
export class SimpleReuseStrategy implements RouteReuseStrategy {
public static handlers: { [key: string]: DetachedRouteHandle } = {}
/** 表示对所有路由允许复用 如果你有路由不想利用可以在这加一些业务逻辑判断 */
public shouldDetach(route: ActivatedRouteSnapshot): boolean {
return true;
}
/** 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象 */
public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
SimpleReuseStrategy.handlers[route.routeConfig.path] = handle
}
/** 若 path 在缓存中有的都认为允许还原路由 */
public shouldAttach(route: ActivatedRouteSnapshot): boolean {
return !!route.routeConfig && !!SimpleReuseStrategy.handlers[route.routeConfig.path]
}
/** 从缓存中获取快照,若无则返回nul */
public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
if (!route.routeConfig) {
return null
}
return SimpleReuseStrategy.handlers[route.routeConfig.path]
}
/** 进入路由触发,判断是否同一路由 */
public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig
}
}
在appModule中启用该自定义的路由策略
providers: [
{ provide: RouteReuseStrategy, useClass: SimpleReuseStrategy }
]
以上代码来源:这里
下面才是主菜:
上面的配置你可以顺利的实现路由的复用,但是大部分业务中都使用了模块懒加载(loadChildren),这时候你会发现页面复用没有效果。
路由配置
path: "",
component: LayoutComponent,
children: [
{
path: "menu",
loadChildren: "./menu/menu.module#MenuModule",
data: {
key: "menu"
}
},
{
path: "user",
loadChildren: "./user/user.module#UserModule",
data: {
key: "user"
}
}
]
重写路由策略
这里代码就不再重新写了,只说关键点,在懒加载的路由中,上面代码中使用的route.routeConfig.path不能用来作为关键字存储缓存(为什么?额,只是追踪了下发现能缓存页面的树结构和变量,但是不能恢复页面,那么就看shouldAttach方法,发现shouldAttach方法中route.routeConfig.path一直是空的!!!
{path: "", component: ƒ}
)。
有些人肯定注意到了新的路由配置多了个key,是的,你想的没错,把重写路由的代码中所有的route.routConfig.path 改为route.data.key
就能够解决这个问题了。
总结
这个解决办法不是唯一的,你也可以用其他方式处理这个唯一标识符,还有一点记得手动清除页面缓存(如果你刷新页面的话,当我没说), 不然页面缓存会一直存在。不会清除???懒???额,好吧,注入自定义策略SimpleReuseStrategy到你删除缓存的地方,
delete delete SimpleReuseStrategy.handlers[key];