使用场景

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

  概述:

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. 「雕爷学编程」Arduino动手做(20)—水银开关模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...

  2. docker基本维护命令

    docker search centos ##查服务器上面的镜像:docker images ##查本地的镜像.docker pull centos ##拉镜像. docker run centos ...

  3. jQuery学习的几个不是问题的问题

    原文在我的GitHubhttps://www.sogeisetsugo.tk/myBlog/jQuery学习的几个不是问题的问题

  4. js 获取table tr td内的select 和input text

    $("#TableList tr").each(function () {                //for (var i = 1; i <= AM_index; i ...

  5. strut2登陆注册验证码

    1. 生成图片和验证码 package com.jmu.code; import java.awt.Color; import java.awt.Font; import java.awt.Graph ...

  6. HDU5293 树链剖分+树形DP

    =-=抓住叶节点往上揪 Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K ...

  7. SQL——SELECT、UPDATE、DELETE和INSERT INTO

    SQL是一种ANSI的标准计算机语言.ANSI:美国国家标准化组织.除SQL标准外,大部分SQL数据库都拥有私有的扩展.SQL对大小写不敏感.某些数据库系统要求在SQL命令末端使用分号,这样可以执行一 ...

  8. PHP数组简单操作

    1.数字索引数组 1.1创建一个数组 php中最常用的两个类型是:数组,字符串.数组也分为两种,一种是数字索引,一种是关键是索引,关键字索引有点像python中字典的意思.数字索引类型的数组的创建方法 ...

  9. 1000 千米高空俯瞰 React Native

    一.历史:React Native 从开始到现在 React Native 的定位是通过 React 构建原生 App: A framework for building native apps wi ...

  10. StreamSets使用指南

    StreamSets使用指南 最近在调研Streamsets,照猫画虎做了几个最简单的Demo鉴于网络上相关资料非常少,做个记录. 1.简介 Streamsets是一款大数据实时采集和ETL工具,可以 ...