angular4 路由重用策略 RouterReuseStrategy
单页面应用现在是主流,随之而来的缺点:页面间切换时不能保存状态
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方法:存储上一个页面的快照
2.关闭路由有几种情况:
i 打开A页面后 打开B页面 关闭B页面(此时B页面没有快照) -> 触发store方法
ii 打开A页面后 打开B页面 关闭A页面 (此时A页面有快照) -> 不触发store方法
iii 打开A页面后 打开B页面 回到A页面 关闭A页面 (此时A页面有快照) ->不触发store方法
iii 打开A页面后 打开B页面 回到A页面 关闭B页面 (此时B页面有快照) ->不触发store方法
因此页面在没有快照的时候关闭 需要在store方法里做一个暂缓删除的操作(先记录key 进去新页面后 再删除key)
这样页面的ngOnDestroy()方法才能执行 才能避免事件重复监听(在ngOnDestroy()中执行)
相关的知识点:
ActivatedRouteSnapshot:包含当前插座中加载组件某一特定时间路由信息
RouteReuseStrategy:路由复用策略
DetachedRouteHandle:组件当前所有状态(路由快照
import {ActivatedRouteSnapshot, RouteReuseStrategy, DetachedRouteHandle} from '@angular/router;
export class ExtensionRouteReuseStrategy implements RouteReuseStrategy {
private static waitDelete:string;
public static storedRoutes: Map<string, DetachedRouteHandle> = new Map<string, DetachedRouteHandle>();
constructor(){
//关闭操作(右上角或者history页面)
this.storageNotifyRouter.destoryTopic.subscribe((key) => {
this.processDestory(key);
});
};
//是否缓存【离开路由时触发】
shouldDetach(route: ActivatedRouteSnapshot): boolean {
if (route.data && route.data.key) {
return true;
}
return false;
}
//缓存组件【离开路由时触发】
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
const key = this.findStoreKey(route);
const key$$ = this.lastClosedKey + _SPLIT;
//未存储快照的情况下 跳转新页面 再删key
if (this.waitDeleteRoutes.size > 0) {
const array = Array.from(this.waitDeleteRoutes.keys());
for (const deletekey of array) {
if (deletekey == key) {
const oldHandle = handle as { componentRef: ComponentRef<any> };
oldHandle.componentRef.destroy();
}
this.waitDeleteRoutes.delete(deletekey);
}
return;
}
//存储上一个页面快照 进入新页面
if (handle && !(key === this.lastClosedKey || key.startsWith(key$$))) {
this.lastClosedKey = '';
this.storedRoutes.set(key, handle);
}
}
//是否还原【进入路由时触发】
shouldAttach(route: ActivatedRouteSnapshot): boolean {
const key = this.findRetrieveKey(route);
const result: boolean = !!key && !!this.storedRoutes.get(key);
return result;
}
//还原路由【进入路由时触发】
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
const key = this.findRetrieveKey(route);
let handle = null;
if (key && this.storedRoutes.get(key)) {
handle = this.storedRoutes.get(key);
this.routerNotifyStorage.notifyRetrieve(key);
}
return handle;
}
//是否复用路由【进入路由时触发】
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
const result: boolean = future.routeConfig === curr.routeConfig;
return result;
}
findStoreKey(route: ActivatedRouteSnapshot): string {
let key = "";
if (route.data && route.data.key) {
if (route.children[0] && route.children[0].data && route.children[0].data.key) {
this.findStoreKey(route.children[0]);
} else {
key = route.data.key;
}
}
return key;
}
findRetrieveKey(route: ActivatedRouteSnapshot): string {
let key = "";
if (route.data && route.data.key) {
key = route.data.key;
}
return key;
}
processDestory(key: string, waiteDelete: boolean = true) {
this.lastClosedKey = key;
let existKey: boolean = false;
const array: string[] = Array.from(this.storedRoutes.keys());
for (const keyStored of array) {
const key$$ = key + _SPLIT;
//存储快照的情况下 删除快照
if (key === keyStored || keyStored.startsWith(key$$)) {
const oldHandle = this.storedRoutes.get(keyStored) as { componentRef: ComponentRef<any> };
oldHandle.componentRef.destroy();
this.storedRoutes.delete(keyStored);
existKey = true;
}
}
//未存储快照 先存当前页面key
if (!existKey && waiteDelete) {
this.waitDeleteRoutes.add(key);
}
}
}
🌊 后续
保存快照
在离开路由时保存上一个页面快照,并emit一个事件给左边的菜单组件和右边的tab组件,告诉它们路由路径已改变,同时把新的路由路径作为参数传过去
然后在左边的菜单组件和右边的tab组件里subscribe事件里去监听变化,替换新的路由路径。
这样在点击它们的时候就会重定向到新的路由路径,而快照已保存。
删除快照
在点击右边tab组件里的关闭按钮或者点击页面上的关闭按钮时,emit一个删除快照的事件,同时把路由路径作为参数传过去
然后在路由复用策略的ts文件中的subscribe事件里去监听这个事件,然后执行对应路由的processDestroy()方法

浙公网安备 33010602011771号