]>
Commit | Line | Data |
---|---|---|
1 | import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router' | |
2 | import { Injectable } from "@angular/core"; | |
3 | ||
4 | @Injectable() | |
5 | export class CustomReuseStrategy implements RouteReuseStrategy { | |
6 | storedRouteHandles = new Map<string, DetachedRouteHandle>() | |
7 | recentlyUsed: string | |
8 | ||
9 | private readonly MAX_SIZE = 2 | |
10 | ||
11 | // Decides if the route should be stored | |
12 | shouldDetach (route: ActivatedRouteSnapshot): boolean { | |
13 | return this.isReuseEnabled(route) | |
14 | } | |
15 | ||
16 | // Store the information for the route we're destructing | |
17 | store (route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { | |
18 | if (!handle) return | |
19 | ||
20 | const key = this.generateKey(route) | |
21 | this.recentlyUsed = key | |
22 | ||
23 | console.log('Storing component %s to reuse later.', key); | |
24 | ||
25 | (handle as any).componentRef.instance.disableForReuse() | |
26 | ||
27 | this.storedRouteHandles.set(key, handle) | |
28 | ||
29 | this.gb() | |
30 | } | |
31 | ||
32 | // Return true if we have a stored route object for the next route | |
33 | shouldAttach (route: ActivatedRouteSnapshot): boolean { | |
34 | const key = this.generateKey(route) | |
35 | return this.isReuseEnabled(route) && this.storedRouteHandles.has(key) | |
36 | } | |
37 | ||
38 | // If we returned true in shouldAttach(), now return the actual route data for restoration | |
39 | retrieve (route: ActivatedRouteSnapshot): DetachedRouteHandle { | |
40 | if (!this.isReuseEnabled(route)) return undefined | |
41 | ||
42 | const key = this.generateKey(route) | |
43 | this.recentlyUsed = key | |
44 | ||
45 | console.log('Reusing component %s.', key) | |
46 | ||
47 | const handle = this.storedRouteHandles.get(key) | |
48 | if (!handle) return handle; | |
49 | ||
50 | (handle as any).componentRef.instance.enabledForReuse() | |
51 | ||
52 | return handle | |
53 | } | |
54 | ||
55 | // Reuse the route if we're going to and from the same route | |
56 | shouldReuseRoute (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { | |
57 | return future.routeConfig === curr.routeConfig | |
58 | } | |
59 | ||
60 | private gb () { | |
61 | if (this.storedRouteHandles.size >= this.MAX_SIZE) { | |
62 | this.storedRouteHandles.forEach((r, key) => { | |
63 | if (key === this.recentlyUsed) return | |
64 | ||
65 | console.log('Removing stored component %s.', key); | |
66 | ||
67 | (r as any).componentRef.destroy() | |
68 | this.storedRouteHandles.delete(key) | |
69 | }) | |
70 | } | |
71 | } | |
72 | ||
73 | private generateKey (route: ActivatedRouteSnapshot) { | |
74 | const reuse = route.data.reuse | |
75 | if (!reuse) return undefined | |
76 | ||
77 | return reuse.key + JSON.stringify(route.queryParams) | |
78 | } | |
79 | ||
80 | private isReuseEnabled (route: ActivatedRouteSnapshot) { | |
81 | return route.data.reuse && route.data.reuse.enabled && route.queryParams['a-state'] | |
82 | } | |
83 | } |