每一个你不满意的现在,都有一个你不努力的曾经. 网站首页 > js
Angular 路由快照 使用RouteReuseStrategy路由复用策略暂
发布时间:2019-07-19 17:01:33 修改时间:2019-07-19 17:01:33 阅读:7391 评论:0 0
首先了解下Angular中RouteReuseStrategy有哪几种方法可操作:
shouldDetach 是否允许复用路由;
store 当路由离开时会触发,存储路由
shouldAttach 是否允许还原路由
retrieve 获取存储路由
shouldReuseRoute 进入路由触发,是否同一路由时复用路由
使用方法(实例环境:Angular5.2,工具vscode)
1、在\src\app目录下创建app-route-reuse-strategy.ts文件,内容如下:
import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router'; export class AppRouteReuseStrategy implements RouteReuseStrategy { public static handlers: { [key: string]: DetachedRouteHandle } = {}; private static waitDelete: string; // 删除 public static deleteRouteSnapshot(name: string): void { if (AppRouteReuseStrategy.handlers[name]) { delete AppRouteReuseStrategy.handlers[name]; } else { AppRouteReuseStrategy.waitDelete = name; } } /** 表示对所有路由允许复用 如果你有路由不想利用可以在这加一些业务逻辑判断 */ public shouldDetach(route: ActivatedRouteSnapshot): boolean { // 添加控制器过滤 false则不对其缓存,反之... if (!route.data.keep) { return false; } if (!route.routeConfig || route.routeConfig.loadChildren) { return false; } return true; } /** 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象 */ public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { if (AppRouteReuseStrategy.waitDelete && AppRouteReuseStrategy.waitDelete === route.routeConfig.path) { // 如果待删除是当前路由则不存储快照 AppRouteReuseStrategy.waitDelete = null; return; } AppRouteReuseStrategy.handlers[route.routeConfig.path] = handle; } /** 若 path 在缓存中有的都认为允许还原路由 */ public shouldAttach(route: ActivatedRouteSnapshot): boolean { return !!route.routeConfig && !!AppRouteReuseStrategy.handlers[route.routeConfig.path]; } /** 从缓存中获取快照,若无则返回null */ public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { if (!route.routeConfig) { return null; } return AppRouteReuseStrategy.handlers[route.routeConfig.path]; } /** 进入路由触发,判断是否同一路由 */ public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { return future.routeConfig === curr.routeConfig; } }
2、在app.module.ts中导入AppRouteReuseStrategy模块
import { RouteReuseStrategy } from '@angular/router'; import { AppRouteReuseStrategy } from './app-route-reuse-strategy'; // ... providers: [ {provide: RouteReuseStrategy, useClass: AppRouteReuseStrategy} ]
3、目标组件TS文件中导入及定义(注意路径)
import { AppRouteReuseStrategy } from '../../app-route-reuse-strategy'; import { ActivatedRoute, Router, NavigationEnd } from '@angular/router'; import { Title } from '@angular/platform-browser'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/mergeMap'; @Component({ selector: 'app-main', templateUrl: './main.component.html', styleUrls: ['./main.component.css'], providers: [AppRouteReuseStrategy] }) // 路由列表 menuList: Array<{ title: string, module: string, power: string, isSelect: boolean }> = []; constructor( private router: Router, private activatedRoute: ActivatedRoute, private titleService: Title ) { // 路由事件 this.router.events.filter(event => event instanceof NavigationEnd) .map(() => this.activatedRoute) .map(route => { while (route.firstChild) { route = route.firstChild; } return route; }) .filter(route => route.outlet === 'primary') .mergeMap(route => route.data) .subscribe((event) => { // 路由data的标题 const title = event['title']; this.menuList.forEach(p => p.isSelect = false); const menu = { title: title, module: event['module'], power: event['power'], isSelect: true}; this.titleService.setTitle(title); const exitMenu = this.menuList.find(info => info.title === title); if (exitMenu) { // 如果存在不添加,当前表示选中 this.menuList.forEach(p => p.isSelect = p.title === title); return ; } this.menuList.push(menu); }); } // 关闭选项标签 closeUrl(module: string, isSelect: boolean) { // 当前关闭的是第几个路由 const index = this.menuList.findIndex(p => p.module === module); // 如果只有一个不可以关闭 if (this.menuList.length === 1) { return; } this.menuList = this.menuList.filter(p => p.module !== module); // 删除复用 AppRouteReuseStrategy.deleteRouteSnapshot(module); if (!isSelect) { return; } // 显示上一个选中 let menu = this.menuList[index - 1]; if (!menu) { // 如果上一个没有,下一个选中 menu = this.menuList[index]; } this.menuList.forEach(p => p.isSelect = p.module === menu.module ); // 显示当前路由信息 this.router.navigate(['admin/' menu.module]); }
4、路由设置,路由中添加参数
data: { title: '用户列表', module: 'user-list', keep: true, power: ''}
其中module值与path一致,keep值是个boolean(也就是AppRouteReuseStrategy中shouldDetach一个判断,是否对其路由状态进行暂存;如否,则每次进入路由都会进行初始化请求,反之...)
4、组件布局结构样式,参考标示性段落,里面部分有实例中的元素可忽略。
临时性Tab溢出我用scrollWidth 与 offsetWidth判断显示与否及按钮滚动距离控制。
<div class="interim-nav"> <div class="scroll-tabs" #scrollNav> <span *ngFor="let menu of menuList" class="dg-tabs"> <span *ngIf="menu.isSelect"> <span class="dg-tab" routerLink="{{ menu.module }}" routerLinkActive='active'>{{menu.title}}</span> <a (click)="closeUrl(menu.module,menu.isSelect)" title="删除" *ngIf="menuList.length === 1 ? false : true"> <i class="anticon anticon-close"></i> </a> </span> <span *ngIf="!menu.isSelect"> <span class="dg-tab" routerLink="{{ menu.module }}" routerLinkActive='active'>{{menu.title}}</span> <a (click)="closeUrl(menu.module,menu.isSelect)" title="删除" *ngIf="menuList.length === 1 ? false : true"> <i class="anticon anticon-close"></i> </a> </span> </span> </div> <div class="scroll-btn" *ngIf="scrollNav.scrollWidth > scrollNav.offsetWidth ? true : false"> <a title="左移" (click)="move(scrollNav, 'lt')" class="text999"><i class="anticon anticon-fast-backward"></i></a> <i class="anticon anticon-pause"></i> <a title="右移" (click)="move(scrollNav, 'rt')" class="text999"><i class="anticon anticon-fast-forward"></i></a> </div> </div> 样式仅供参考,具体根据设计而定 .interim-nav{ display:flex; position: relative; border-bottom:1px #ececec solid; border-top:1px #ececec solid; background-color:white; height:42px; line-height:42px; z-index:1; } .interim-nav::before,.interim-nav::after{content:"";position: absolute;top:0;width:25px;height:100%;z-index:2;} .interim-nav::before{ left:0; background-image:linear-gradient(to left,white,rgba(255,255,255,.5)); } .interim-nav::after{ right:145px; background-image:linear-gradient(to right,rgba(255,255,255,.5),white); } .interim-nav .scroll-tabs{position:relative;flex:1;padding:0 10px;margin:0 12px;white-space:nowrap;overflow:hidden;} .interim-nav .dg-tabs{display:inline-block;cursor: pointer;margin-right:32px;}
最后,我们在登出后台管理系统时,需要移除Tabs列表,否则在不刷新浏览器的情况下,再次登入会报错,具体的忘做记录,这里就不对其表示了;我对其上述menuList做了循环删除操作,以便清空所有快照,再次登录方可进行。
this.menuList.forEach(item => { AppRouteReuseStrategy.deleteRouteSnapshot(item.module); });
最后就是打包发布,尽量使用ng build --prod 这样会小很多,提升初始化打开速度,注意的一点是未定义的直接删除掉或在ts中对其定义下,否则打包过程中会报错。
回复列表
关键字词:nbsp,span,style,font-size,0.5em,gt
上一篇:css常用属性