使用场景

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

  概述:

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路由复用策略的更多相关文章

  1. 使用原生js与jQuery分别实现一个简单的tab页签

    tab页签通常适用于空间有限而内容较多同时兼顾页面美观度不给用户一种信息过量视觉疲劳的情形.使用面非常广,下面我们用两种方法简单实现之. 首先,构建页面元素.页签的可点击部分我们通常用列表来承载,包括 ...

  2. Tab页签切换

    js之tab页签切换效果       现在web网站,很多地都需要用到tab页签. 示例:         $(document).ready(function(){               va ...

  3. tab页签

    <div class="fl" id="newsBox"> <div class="tab1 grayBar"> & ...

  4. bootStrap中Tab页签切换

    关于$().tab()一般用来实现标签页和胶囊链接内容片段的切换,或是相关内容的页面导航: <ul class="nav nav-tabs" id="myTab&q ...

  5. ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  6. bootstrap 切换页签失效的解决方法

    概述 bootstrap开发标签页时,标签页显示正常,但点击时候对应内容区域没有变化. 具体症状与解决方案 1.标签页UI出现,但点击无反应,标签页UI并未随点击进行切换 先检查bootstrap.c ...

  7. android123 zhihuibeijing 新闻中心-新闻 页签 ViewPagerIndicator实现

    ## ViewPagerIndicator ## 使用导入ViewPagerIndicator库的方式相当于可以改源码,打包编译Eclips可以自动完成. ViewPager指针项目,在使用ViewP ...

  8. 网页打印A4纸-----表格在跨页时自动换页打印的实现 (转)

    在最近所做的一个项目中,需要通过网页来打印不少的表单,但是又不想每个打印页签各占用一个页面,这样就需要生存很多不同的冗余页面,为了减少冗余,所有的表单通过jquery的页签tab来实现的. 一 :基本 ...

  9. 值得分享的Bootstrap Ace模板实现菜单和Tab页效果(转)

    Ace模板地址:http://code.google.com/p/ace-engine/wiki/AceTemplate(有时会打不开) Ace英文官网:http://wrapbootstrap.co ...

随机推荐

  1. .net core BundlerMinifier.BundlerBuildTask 任务意外失败

    BundlerMinifier.BundlerBuildTask : 捆绑和缩小CSS.JS和HTML文件 BundlerMinifier.BundlerBuildTask 任务意外失败处理: 1.在 ...

  2. Proteus仿真时出现Cannot open‘C:\Users\...\LISA7605.SDF’的错误

    目录 打开环境变量 更改环境变量 打开环境变量 更改环境变量 "用户变量"和"系统变量"栏里,找到TEMP与TMP,都改成%SystemRoot%\TEMP 改 ...

  3. Django模板之模板继承(extends/block)

    Django模版引擎中最强大也是最复杂的部分就是模版继承了.模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 block. 模板继承: 1.    ...

  4. MySQL索引及优化(3)设计数据库

    一.范式和反范式 优秀的库表设计是高性能数据库的基础.如何才能设计出高性能的库表结构呢?这里必须要提到数据库范式.范式是基础规范,反范式是针对性设计. 1.1.范式 范式是设计数据库结构过程中所要遵循 ...

  5. SpringAOP注解报错:java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut selectAll

    原因 我使用的aspectjweaver.jar版本是1.5.1,版本过低,导致报错. 需要下载高本版的aspectjweaver.jar. 解决办法 在这里下载:https://mvnreposit ...

  6. 蒲公英 · JELLY技术周刊 Vol.08 -- 技术周刊 · npm install -g typescript@3.9.3

    登高远眺 沧海拾遗,积跬步以至千里 基础技术 官宣: Typescript 3.9 正式发布 TypeScript 3.9 正式发布,这个版本主要聚焦于性能.改进某些特性和提升稳定性.编译器效率在这一 ...

  7. Cypress系列(2)- Cypress 框架的详细介绍

    如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html Cypress 简介 基于 JavaSc ...

  8. 二、Spring装配Bean

    内容 声明bean 构造器注入和Setter方法注入 装配Bean 控制bean的创建和销毁 关键词 装配(wiring) 组件扫描(component scanning) 自动装配(AutoWiri ...

  9. linux-offen-used-commands

    文件系统 cd 进入目录 ls 列出目录信息,ls -al (或 ll)列出详细信息 touch 新建文件 mkdir 新建目录 rm 删除文件或目录 cp 复制 mv 移动(或重命名) 搜索.查找. ...

  10. python常见面试题讲解(八)提取不重复的整数

    题目描述 输入一个int型整数,按照从右向左的阅读顺序,返回一个不含重复数字的新的整数. 输入描述: 输入一个int型整数 输出描述: 按照从右向左的阅读顺序,返回一个不含重复数字的新的整数 示例1 ...