单页面应用现在是主流,随之而来的缺点:页面间切换时不能保存状态
angular4出了一个RouteReuseStrategy路由重用策略可以让组件所有的state和渲染好的html存起来,然后在切回去的时候再调出来。
export declare abstract class RouteReuseStrategy{ abstract shouldReuseRoute():Boolean abstract shouldAttach():Boolean abstract retrieve():DetachedRouteHandle | null abstract shouldDetach():Boolean abstract store():void }
替换一旦发生,某些组件将被丢弃
这时shouldDetech,store将被调用,用于缓存即将被丢弃的组件
有组件丢弃,自然有组件替补进来
这时shouldAttach retreive将被调用,用于调出缓存的组件
? 应用场景
1.进入某个路由页面,进行操作(比如进入到子路由,进行了查询操作),切换页面再返回,能还原到之前的操作状态;
2.切换右边的tab,能进入到对应的路由页面(操作后的状态);
3.点击右边tab里的关闭按钮或页面上的关闭按钮,删除某个路由页面的快照,再次点开这个路由页面,页面恢复初始状态;
? 下面是具体实现
要注意的几个点:
1. 路由快照是在离开页面时生成并存储(执行store方法),因此从父路由到子路由也会触发store方法,这个时候想存储子路由的快照,需要在store方法里处理。
2.store方法在存储快照的时候,key值应该存当前路由路径(不管是父路由还是子路由),而不是存routes对象的data的key值,
这样在切换页面的时候,如果快照对应的key是路由路径,在点击菜单时可以重定向到子路由(因为可以把这个路径作为参数传过去)。
3.切换一个新的路由页面后,不再切换直接点击关闭按钮进行关闭路由的操作,依然会触发store方法,因此需要处理:这种情况下关闭操作不应该保存快照,保存的话再次打开会还原操作。
相关的知识点:
ActivatedRouteSnapshot:包含当前插座中加载组件某一特定时间路由信息
RouteReuseStrategy:路由复用策略
DetachedRouteHandle:组件当前所有状态(路由快照import {ActivatedRouteSnapshot, RouteReuseStrategy, DetachedRouteHandle} from '@angular/routerexport class ExtensionRouteReuseStrategy implements RouteReuseStrategy {
private static waitDelete:string; public static storedRoutes: Map<string, DetachedRouteHandle> = new Map<string, DetachedRouteHandle>(); constructor(){}; //是否缓存[离开路由时触发] shouldDetach(route: ActivatedRouteSnapshot): boolean { return true; } //缓存组件[离开路由时触发] store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
if(this.waitDelete && this.waitDelete==this.getRouteUrl(route)){ this.waitDelete=null return; } this.storedRoutes.set(this.getRouteUrl(route), handle); } //是否还原[进入路由时触发] shouldAttach(route: ActivatedRouteSnapshot): boolean { return !!this.storedRoutes.get(this.getRouteUrl(route)) } //还原路由[进入路由时触发] retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { if (!route.routeConfig) { return null } return this.storedRoutes.get(this.getRouteUrl(route)) } //是否复用路由[进入路由时触发] shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { let result: boolean = future.routeConfig === curr.routeConfig; return result; } //拿到当前路由 private getRouteUrl(route: ActivatedRouteSnapshot){ return route['_routerState'].url } //删除快照 public static deleteRouteSnapshot(name:string):void{ if(this.storedRoutes.get(name)){ this.storedRoutes.delete(name); }else{ this.waitDelete=name; } } }
? 后续
保存快照,代码的关键主要在sotre方法里。
在离开路由时保存快照,并emit一个事件给左边的菜单组件和右边的tab组件,告诉它们路由路径已改变,同时把新的路由路径作为参数传过去
然后在左边的菜单组件和右边的tab组件里subscribe事件里去监听变化,替换新的路由路径。
这样在点击它们的时候就会重定向到新的路由路径,而快照已保存,这样就算的上是保存了状态了。
删除快照,则是在点击右边tab组件里的关闭按钮或者点击页面上的关闭按钮时,emit一个删除快照的事件,同时把路由路径作为参数传过去
然后在路由复用策略的ts文件中的subscribe事件里去监听这个事件,然后执行对应路由的deleteRouteSnapshot()方法(删除快照的方法)