用于实现tab页签切换页面的angular路由复用策略
使用场景
打开菜单页面的时候,出现对应页面的页签。切换页签,原来的页面信息状态保留,关闭页签则保留的信息删除。使用路由复用策略,保存路由快照。
实现效果如图所示

实现过程
概述:
1、在app.module.ts注册
providers: [
{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy }
],
2、新建RouteReuseStrategy
新建一个CustomReuseStrategy.ts
贴上代码(解决了位于三级菜单的页面与位于一级菜单或者二级菜单无法跳转的问题之后的代码)
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: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig;
}
/** 表示对所有路由允许复用 如果你有路由不想利用可以在这加一些业务逻辑判断,这里判断是否有data数据判断是否复用 */
shouldDetach(route: ActivatedRouteSnapshot): boolean {
if (!route.data.keep) {
return false;
}
if (!route.routeConfig || route.routeConfig.loadChildren) {
return false;
}
return true;
}
/** 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象 */
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
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: ActivatedRouteSnapshot): boolean {
const url = this.getFullRouteUrl(route);
return AppReuseStrategy.routeCache.has(url);
}
/** 从缓存中获取快照,若无则返回nul */
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
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: ActivatedRouteSnapshot): void {
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: ActivatedRouteSnapshot): string {
return this.getFullRouteUrlPaths(route).filter(Boolean).join('/').replace('/', '_');
}
private getFullRouteUrlPaths(route: ActivatedRouteSnapshot): string[] {
const paths = this.getRouteUrlPaths(route);
return route.parent ? [...this.getFullRouteUrlPaths(route.parent), ...paths] : paths;
}
private getRouteUrlPaths(route: ActivatedRouteSnapshot): string[] {
return route.url.map(urlSegment => urlSegment.path);
}
private getRouteData(route: ActivatedRouteSnapshot): IRouteConfigData {
return route.routeConfig && route.routeConfig.data as IRouteConfigData;
}
/** 用于删除路由快照*/
public static deleteRouteSnapshot(url: string): void {
let arr: any = []
arr = url.split('?')
url = arr[0]
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;
}
}
}
附上相关API文档:
[RouteReuseStrategy](https://www.angular.cn/api/router/RouteReuseStrategy)
3、关闭页签的时候,同时删除快照
解决办法:在实现页签的页面,关闭按钮那里,删除页签数组之后,加入以下代码:
// link就是当前关闭页面的路由
setTimeout(()=>{
AppReuseStrategy.deleteRouteSnapshot(link);
}, 0)
4、其他
值得注意的是,如果页面中有定时器,离开页面的时候,需要暂时删除该定时器。
但保存路由快照之后,离开该页面的时候,不经过ngOnDestroy。
解决办法:
this.router.events.filter(event => event instanceof NavigationEnd)
.subscribe((event) => {
// 路由data的标题
clearInterval(this.interval)
});
用于实现tab页签切换页面的angular路由复用策略的更多相关文章
- 使用原生js与jQuery分别实现一个简单的tab页签
tab页签通常适用于空间有限而内容较多同时兼顾页面美观度不给用户一种信息过量视觉疲劳的情形.使用面非常广,下面我们用两种方法简单实现之. 首先,构建页面元素.页签的可点击部分我们通常用列表来承载,包括 ...
- Tab页签切换
js之tab页签切换效果 现在web网站,很多地都需要用到tab页签. 示例: $(document).ready(function(){ va ...
- tab页签
<div class="fl" id="newsBox"> <div class="tab1 grayBar"> & ...
- bootStrap中Tab页签切换
关于$().tab()一般用来实现标签页和胶囊链接内容片段的切换,或是相关内容的页面导航: <ul class="nav nav-tabs" id="myTab&q ...
- ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持
目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...
- bootstrap 切换页签失效的解决方法
概述 bootstrap开发标签页时,标签页显示正常,但点击时候对应内容区域没有变化. 具体症状与解决方案 1.标签页UI出现,但点击无反应,标签页UI并未随点击进行切换 先检查bootstrap.c ...
- android123 zhihuibeijing 新闻中心-新闻 页签 ViewPagerIndicator实现
## ViewPagerIndicator ## 使用导入ViewPagerIndicator库的方式相当于可以改源码,打包编译Eclips可以自动完成. ViewPager指针项目,在使用ViewP ...
- 网页打印A4纸-----表格在跨页时自动换页打印的实现 (转)
在最近所做的一个项目中,需要通过网页来打印不少的表单,但是又不想每个打印页签各占用一个页面,这样就需要生存很多不同的冗余页面,为了减少冗余,所有的表单通过jquery的页签tab来实现的. 一 :基本 ...
- 值得分享的Bootstrap Ace模板实现菜单和Tab页效果(转)
Ace模板地址:http://code.google.com/p/ace-engine/wiki/AceTemplate(有时会打不开) Ace英文官网:http://wrapbootstrap.co ...
随机推荐
- for循环中break和continue的区别
break 会立即退出循环,强制执行循环后面的语句 默认只会终止紧邻的循环,如果要终止其他循环,需要给循环起名字 例如: name:for(var i = 0; i < 5; i++){ for ...
- Django模板之模板组件(include)
可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中的一个小功能块,然后在需要使用的地方,文件的任意位置按如下语法导入即可. 模板组件: 新建一个组件zujian.html文件(一个固定写好 ...
- Blazor WebAssembly 船新项目下载量测试 , 仅供参考.
前言: 昨天 Blazor WebAssembly 3.2 正式发布了. 更新 VS2019后就能直接使用. 新建了两个PWA项目, 一个不用asp.net core (静态部署), 一个使用as ...
- Redis学习笔记(十四)Sentinel(哨兵)(上)
最近谈到Redis就会听到哨兵模式,工作期间同事也分享过关于哨兵模式的知识,但由于工作忙(给自己找个借口)没有没认真看,现在恶补下,老样子还是分上篇应用,下篇看实现过程,下面我们来看下哨兵到底是啥? ...
- PAT-1078 Hashing (散列表 二次探测法)
1078. Hashing The task of this problem is simple: insert a sequence of distinct positive integers in ...
- CF916C
题目链接:http://codeforces.com/contest/916/problem/C 题目大意: 用\(n\)个结点,\(m\)条边(每条边的权值范围为[1, 109]) 构造出一个无向带 ...
- 10个典型的JavaScript面试题
问题1:作用域 考虑如下代码: JavaScript 1 2 3 4 5 6 7 (function() { var a = b = 5; })(); console.log(b) ...
- Kd Tree算法详解
kd树(k-dimensional树的简称),是一种分割k维数据空间的数据结构,主要应用于多维空间关键数据的近邻查找(Nearest Neighbor)和近似最近邻查找(Approximate Nea ...
- Java——java.lang.NumberFormatException: For input string: ""
java.lang.NumberFormatException: For input string: "" at java.lang.NumberFormatException.f ...
- 关于lua的那些事
1.lua是一个脚本语言,由巴西里约热内卢天主教大学Roberto Ierusalimschy.Waldemar Celes 和 Luiz Henrique de Figueiredo三人所组成的研究 ...