Angular5中使用back按钮返回时恢复页面原有状态的方案
在Angular 5中实现路由跳转后返回复用页面状态的方案
嘿,这个需求完全可以实现!核心思路是让Angular缓存住r1组件的实例,而不是在离开时销毁它——这和Ionic的push/pop视图栈逻辑本质是一样的。不用额外的数据服务或localStorage,只需要自定义路由复用策略(RouteReuseStrategy)就能搞定,具体步骤如下:
1. 创建自定义路由复用策略类
Angular默认会销毁离开的组件,我们需要实现RouteReuseStrategy接口,告诉Angular哪些路由需要缓存、如何缓存和恢复。创建一个custom-route-reuse-strategy.ts文件:
import { RouteReuseStrategy, DetachedRouteHandle, ActivatedRouteSnapshot } from '@angular/router'; export class CustomRouteReuseStrategy implements RouteReuseStrategy { // 用Map存储缓存的路由实例 private storedRoutes = new Map<string, DetachedRouteHandle>(); // 判断是否复用当前路由(默认逻辑,不用改) shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { return future.routeConfig === curr.routeConfig; } // 判断当前路由是否需要被缓存(通过路由data里的reuse标记) shouldDetach(route: ActivatedRouteSnapshot): boolean { return route.data && route.data['reuse'] === true; } // 缓存路由实例 store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { if (this.shouldDetach(route)) { const routeKey = this.generateRouteKey(route); this.storedRoutes.set(routeKey, handle); } } // 判断是否应该恢复缓存的路由 shouldAttach(route: ActivatedRouteSnapshot): boolean { const routeKey = this.generateRouteKey(route); return this.storedRoutes.has(routeKey); } // 获取缓存的路由实例 retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { const routeKey = this.generateRouteKey(route); return this.storedRoutes.get(routeKey) || null; } // 生成唯一路由Key(避免同路径不同参数的路由混淆) private generateRouteKey(route: ActivatedRouteSnapshot): string { let key = route.routeConfig?.path || ''; // 如果路由有参数,把参数也加入Key,比如r1/:id的不同id会生成不同Key if (route.paramMap.keys.length) { key += JSON.stringify(route.paramMap); } return key; } }
2. 在模块中注册自定义策略
打开AppModule,把我们的自定义策略替换掉Angular默认的路由复用策略:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouteReuseStrategy } from '@angular/router'; import { CustomRouteReuseStrategy } from './custom-route-reuse-strategy'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { R1Component } from './r1/r1.component'; import { R2Component } from './r2/r2.component'; @NgModule({ declarations: [AppComponent, R1Component, R2Component], imports: [BrowserModule, AppRoutingModule], providers: [ // 替换默认路由复用策略 { provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy } ], bootstrap: [AppComponent] }) export class AppModule { }
3. 给需要缓存的路由添加标记
在路由配置文件(比如app-routing.module.ts)中,给r1路由的data属性加上reuse: true,告诉策略这个路由需要缓存:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { R1Component } from './r1/r1.component'; import { R2Component } from './r2/r2.component'; const routes: Routes = [ { path: 'r1', component: R1Component, data: { reuse: true } }, // 标记需要缓存 { path: 'r2', component: R2Component }, { path: '', redirectTo: '/r1', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
效果验证
现在当你从r1跳转到r2时,Angular会缓存r1的组件实例——包括你的myList变量、页面滚动位置、表单输入状态等等。当你调用this._location.back()返回r1时,会直接复用之前的实例,不会重新执行组件的ngOnInit或HTTP请求,完美实现类似Ionic的视图栈效果。
额外提示
- 如果r1是带参数的路由(比如
r1/:id),我们的generateRouteKey方法会把参数加入Key,确保不同参数的r1页面分别缓存,不会互相覆盖。 - 如果不需要缓存某个路由,只要去掉
data: { reuse: true }即可,Angular会回到默认的销毁逻辑。
内容的提问来源于stack exchange,提问作者star
相关产品推荐
相关产品推荐

