用于实现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 ...
随机推荐
- 9.4 Go 数据格式
9.4 Go 数据格式 1.1. msgpack格式 官方msgpack官网用一句话总结: It’s like JSON. but fast and small. 简单来讲,它的数据格式与json类似 ...
- tableView的嵌套
1,subTableView需要开启多手势识别,多层tableView都会响应滚动事件(如果底层是scroll 依然会响应,这样滚动tableview时,scroll也会滚动,导致滚动过于灵活)2,通 ...
- PAT-1059 Prime Factors (素数因子)
1059. Prime Factors Given any positive integer N, you are supposed to find all of its prime factors, ...
- POJ2377
题目链接:http://poj.org/problem?id=2377 解题思路: Prim算法. Warning ! 注意考虑重边 ! 其实就是求最大生成树,没什么好说的,就上面那个坑. AC代码: ...
- Android数据传递
直接用一个例子说明,简单粗暴: 数据传递会用到此界面标注id值的三个控件 Activity_zc.xm l 当点击“注册”按钮,会显示注册信息 Activity._show.xml 下面展示zcAct ...
- js常用 方法 封装
// 监听滚动,用于列表页向下加载--------------------------------- function loadmore(callback) { $(window).scroll(fu ...
- MySQL常见6个考题在实际工作中的运用
题目一 MyISAM和InnoDB的区别,什么时候选择MyISAM 参考回答 InnoDB是目前MySQL主流版本(5.6.5.7.8.0)默认的存储引擎,支持事务.外键.行级锁,对于并发条件下要求数 ...
- 《机器学习_09_01_决策树_ID3与C4.5》
简介 先看一个例子,某银行是否给用户放贷的判断规则集如下: if 年龄==青年: if 有工作==是: if 信贷情况==非常好: 放 else: 不放 else: if 有自己的房子==是: if ...
- 整理总结数据库常用sql语句,建议收藏,忘记了可以来看一下
第一节课:sql语言介绍(参照PPT)及基本查询sql学习 1.数据库表的介绍 emp表:员工表 dept表:部门表 salgrady:薪资水平表 Balance: 2.基本的查询语句: 知识点: s ...
- 【译】Welcome to C# 9.0
C# 9.0正在形成,我想分享我们对添加到该语言下个版本的一些主要功能的看法.对于每个新版本的 C#,我们努力使常见的编码方案更加清晰和简单,C# 9.0 也不例外.这次的一个特别重点是支持数据形状的 ...