路由复用策略与方法
2022/11/17 4:24:53
本文主要是介绍路由复用策略与方法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
背景
默认情况下,路由从 A 组件跳转到 B 组件的时候,A 组件的状态也会一并销毁。
但有时候,从 A 组件跳转到 B 组件,再从B 组件切换回 A 组件,我们希望看到A 组件依旧保持原来的状态,表单里面的内容依然存在。
此时,我们就需要 Angular 的路由复用策略,即RouteReuseStrategy
。
RouteReuseStrategy 提供的方法
- shouldDetach:判断是否复用此路由
- store:储存需要复用的路由
- shouldAttach:判断是否启用路由缓存
- retrieve:获取已经储存的路由
- shouldReuseRoute:判断是否应该复用路由
使用方法和步骤
首先,创建一个服务文件: route-cache.service.ts
内容如下:
import { Injectable } from '@angular/core'; import { RouteReuseStrategy, DefaultUrlSerializer, ActivatedRouteSnapshot, DetachedRouteHandle } from "@angular/router"; interface IRouteConfigData { reuse: boolean; } interface ICachedRoute { handle: DetachedRouteHandle; data: IRouteConfigData; } @Injectable() export class RouteCacheService implements RouteReuseStrategy { private routeCache = new Map<string, ICachedRoute>(); shouldReuseRoute( future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot ): boolean { let ret = future.routeConfig === curr.routeConfig; console.log("shouldReuseRoute called", ret); if (ret) { this.addRedirectsRecursively(future); // update redirects } return ret; } shouldDetach(route: ActivatedRouteSnapshot): boolean { const data = this.getRouteData(route); console.log( "shouldDetach check if we want to detach and store route", data && data.reuse ); return data && data.reuse; } store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { const url = this.getFullRouteUrl(route); const data = this.getRouteData(route); this.routeCache.set(url, { handle, data }); this.addRedirectsRecursively(route); //console.log("store route", this.routeCache); } shouldAttach(route: ActivatedRouteSnapshot): boolean { const url = this.getFullRouteUrl(route); console.log( "shouldAttach if retrive route is true", this.routeCache.has(url) ); return this.routeCache.has(url); } retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | any { const url = this.getFullRouteUrl(route); const data = this.getRouteData(route); console.log( "retrive route", data && data.reuse && this.routeCache.has(url) ); return data && data.reuse && this.routeCache.has(url) ? this.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("/"); } 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 | any { return route.routeConfig && (route.routeConfig.data as IRouteConfigData); } }
然后,在根模块里(app.module.ts)引入并注入此服务:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule, Components } from './app-routing.module'; import { AppComponent } from './app.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { HttpClientModule } from '@angular/common/http'; import { MaterialModule } from '@common/material/material.module'; import { ApiService } from '@common/service/api/api.service'; import { SnackBarService } from '@common/material/snack-bar/snack-bar.service'; // 引入默认的路由复用接口类 RouteReuseStrategy 和我们自定义的服务 import { RouteReuseStrategy } from "@angular/router"; import { RouteCacheService } from '@common/service/route/route-cache.service'; @NgModule({ declarations: [ AppComponent, ...Components ], imports: [ BrowserModule, AppRoutingModule, BrowserAnimationsModule, HttpClientModule, MaterialModule, ], providers: [ApiService, SnackBarService, // 注入 RouteCacheService 服务 { provide: RouteReuseStrategy, useClass: RouteCacheService }], bootstrap: [AppComponent] }) export class AppModule { }
最后,哪个路由需要复用(根路由和子路由都如此配置),就添加 data: { reuse: true }
即可:
const routes: Routes = [ { path: '', // data: { reuse: true }, component: InPaymentComponent }, { path: 'update', loadChildren: () => import('./modules/update/update.module').then((m) => m.UpdateModule), }, { path: 'check', loadChildren: () => import('./modules/check/check.module').then((m) => m.CheckModule), } ];
这篇关于路由复用策略与方法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-01为什么公共事业机构会偏爱 TiDB :TiDB 数据库在某省妇幼健康管理系统的应用
- 2024-04-26敏捷开发:想要快速交付就必须舍弃产品质量?
- 2024-04-26静态代码分析的这些好处,我竟然都不知道?
- 2024-04-26你在测试金字塔的哪一层?(下)
- 2024-04-26快刀斩乱麻,DevOps让代码评审也自动起来
- 2024-04-262024年最好用的10款ER图神器!
- 2024-04-2203-为啥大模型LLM还没能完全替代你?
- 2024-04-2101-大语言模型发展
- 2024-04-17基于SpringWeb MultipartFile文件上传、下载功能
- 2024-04-14个人开发者,Spring Boot 项目如何部署