路由在执行过程当中对组件无状态操做,即路由离退时组件状态也一并被删除;固然在绝大多数场景下这是合理的。进入组件时会执行 ngOnInit() 里面的初始化方法,使页面保持最开始的状态。但有些需求须要切换页面的时候,再切换回来该页面时保持原来的状态。此时咱们就须要 Angular 的RouteReuseStrategy 贯穿路由状态并决定构建组件的方式。缓存
RouteReuseStrategy :路由复用策略,提供了几种办法通俗易懂的方法:ide
shouldDetach 是否容许复用路由
store 当路由离开时会触发,存储路由
shouldAttach 是否容许还原路由
retrieve 获取存储路由
shouldReuseRoute 进入路由触发,是否同一路由时复用路由this
1.新建 simple-reuse-strategy.ts,网上已经有大佬写好了,我稍微修改了一下, 路由复用策略默认对全部路由复用 可经过给路由配置项增长data: { keep: true }来进行选择性使用。url
// simple-reuse-strategy.ts // tslint:disable import {RouteReuseStrategy, DefaultUrlSerializer, ActivatedRouteSnapshot, DetachedRouteHandle} from '@angular/router'; export class SimpleReuseStrategy implements RouteReuseStrategy { _cacheRouters: { [key: string]: any } = {}; shouldDetach(route: ActivatedRouteSnapshot): boolean { // 默认对全部路由复用 可经过给路由配置项增长data: { keep: true }来进行选择性使用 // {path: 'search', component: SearchComponent, data: {keep: true}}, if (!route.data.keep) { return false; } else { return true; } } store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { // 按path做为key存储路由快照&组件当前实例对象 // path等同RouterModule.forRoot中的配置 this._cacheRouters[route.routeConfig.path] = { snapshot: route, handle: handle }; } shouldAttach(route: ActivatedRouteSnapshot): boolean { // 在缓存中有的都认为容许还原路由 return !!route.routeConfig && !!this._cacheRouters[route.routeConfig.path]; } retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { // 从缓存中获取快照,若无则返回null if (!route.routeConfig || route.routeConfig.loadChildren || !this._cacheRouters[route.routeConfig.path]) return null; return this._cacheRouters[route.routeConfig.path].handle; } shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { // 同一路由时复用路由 return future.routeConfig === curr.routeConfig; } }
2.将策略注册到模块当中:code
import {RouteReuseStrategy, RouterModule, Routes} from '@angular/router'; import {SimpleReuseStrategy} from './simple-reuse-strategy'; providers: [ /*路由复用策略*/ { provide: RouteReuseStrategy, useClass: SimpleReuseStrategy } ]
3.使用路由复用策略后,ngOnInit 的方法不会再执行,这个时候须要把 ngOnInit的方法写在NavigationEnd里component
// 任意一个页面组件 import {NavigationEnd, Router} from '@angular/router'; constructor(private router: Router) { this.router.events .filter((event) => event instanceof NavigationEnd) .subscribe((event: NavigationEnd) => { // 这里须要判断一下当前路由,若是不加的话,每次路由结束的时候都会执行这里的方法,这里以search组件为例 if (event.url === '/search') { /*在这写须要执行初始化的方法*/ this.search(); } }); }
4.额外问题
退出系统后,换另一个用户登陆,组件状态也会保留,这是不合理的。router
shouldAttach(route: ActivatedRouteSnapshot): boolean { // 在路由是login的时候清空缓存 if(route.routeConfig['path'] === 'login'){ this._cacheRouters = {}; } // 在缓存中有的都认为容许还原路由 return !!route.routeConfig && !!this._cacheRouters[route.routeConfig.path]; }