Browse Source

页签修复

seimin 1 month ago
parent
commit
63c4b689f2

+ 40 - 48
src/app/SimpleReuseStrategy.ts

@@ -1,66 +1,58 @@
1
-import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle, UrlSegment } from '@angular/router';
1
+import {RouteReuseStrategy, DefaultUrlSerializer, ActivatedRouteSnapshot, DetachedRouteHandle} from '@angular/router';
2 2
 
3
+/**
4
+ * 路由复用策略
5
+ */
3 6
 export class SimpleReuseStrategy implements RouteReuseStrategy {
4
-  static cacheRouters = new Map<string, DetachedRouteHandle>();
5 7
 
6
-  public static deleteRouteCache(url): void {
7
-    if (SimpleReuseStrategy.cacheRouters.has(url)) {
8
-      const handle: any = SimpleReuseStrategy.cacheRouters.get(url);
9
-      try {
10
-        handle.componentRef.destory();
11
-      } catch (e) { }
12
-      SimpleReuseStrategy.cacheRouters.delete(url);
13
-    }
8
+  public static handlers: { [key: string]: DetachedRouteHandle } = {};
9
+  private static waitDelete: string;
10
+
11
+  /** 表示对所有路由允许复用 如果你有路由不想利用可以在这加一些业务逻辑判断 */
12
+  public shouldDetach(route: ActivatedRouteSnapshot): boolean {
13
+    return route.routeConfig && route.routeConfig.data && route.routeConfig.data.reuse === true;
14 14
   }
15 15
 
16
-  public static deleteAllRouteCache(): void {
17
-    SimpleReuseStrategy.cacheRouters.forEach((handle: any, key) => {
18
-      SimpleReuseStrategy.deleteRouteCache(key);
19
-    });
16
+  /** 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象 */
17
+  public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
18
+    if (SimpleReuseStrategy.waitDelete && SimpleReuseStrategy.waitDelete === this.getRouteUrl(route)) {
19
+      // 如果待删除是当前路由则不存储快照
20
+      SimpleReuseStrategy.waitDelete = null;
21
+      return;
22
+    }
23
+    SimpleReuseStrategy.handlers[this.getRouteUrl(route)] = handle;
20 24
   }
21 25
 
22
-  // one 进入路由触发,是否同一路由时复用路由
23
-  shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
24
-    return future.routeConfig === curr.routeConfig &&
25
-      JSON.stringify(future.params) === JSON.stringify(curr.params);
26
+  /** 若 path 在缓存中有的都认为允许还原路由 */
27
+  public shouldAttach(route: ActivatedRouteSnapshot): boolean {
28
+    return !!SimpleReuseStrategy.handlers[this.getRouteUrl(route)];
26 29
   }
27 30
 
28
-  // 获取存储路由
29
-  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
30
-    const url = this.getFullRouteURL(route);
31
-    if (route.data.reuse && SimpleReuseStrategy.cacheRouters.has(url)) {
32
-      return SimpleReuseStrategy.cacheRouters.get(url);
33
-    } else {
31
+  /** 从缓存中获取快照,若无则返回nul */
32
+  public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
33
+    if (!route.routeConfig) {
34 34
       return null;
35 35
     }
36
-  }
37 36
 
38
-  // 是否允许复用路由
39
-  shouldDetach(route: ActivatedRouteSnapshot): boolean {
40
-    return Boolean(route.data.reuse);
41
-  }
42
-  // 当路由离开时会触发,存储路由
43
-  store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
44
-    const url = this.getFullRouteURL(route);
45
-    SimpleReuseStrategy.cacheRouters.set(url, handle);
46
-  }
47
-  //  是否允许还原路由
48
-  shouldAttach(route: ActivatedRouteSnapshot): boolean {
49
-    const url = this.getFullRouteURL(route);
50
-    return Boolean(route.data.reuse) && SimpleReuseStrategy.cacheRouters.has(url);
37
+    return SimpleReuseStrategy.handlers[this.getRouteUrl(route)];
51 38
   }
52 39
 
53
-  // 获取当前路由url
54
-  private getFullRouteURL(route: ActivatedRouteSnapshot): string {
55
-    const { pathFromRoot } = route;
56
-    let fullRouteUrlPath: string[] = [];
57
-    pathFromRoot.forEach((item: ActivatedRouteSnapshot) => {
58
-      fullRouteUrlPath = fullRouteUrlPath.concat(this.getRouteUrlPath(item));
59
-    });
60
-    return `/${fullRouteUrlPath.join('/')}`;
40
+  /** 进入路由触发,判断是否同一路由 */
41
+  public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
42
+    return future.routeConfig === curr.routeConfig &&
43
+      JSON.stringify(future.params) === JSON.stringify(curr.params);
44
+  }
61 45
 
46
+  private getRouteUrl(route: ActivatedRouteSnapshot) {
47
+    return route['_routerState'].url.replace(/\//g, '_');
62 48
   }
63
-  private getRouteUrlPath(route: ActivatedRouteSnapshot) {
64
-    return route.url.map(urlSegment => urlSegment.path);
49
+
50
+  public static deleteRouteSnapshot(url: string): void {
51
+    const key = url.replace(/\//g, '_');
52
+    if (SimpleReuseStrategy.handlers[key]) {
53
+      delete SimpleReuseStrategy.handlers[key];
54
+    } else {
55
+      SimpleReuseStrategy.waitDelete = key;
56
+    }
65 57
   }
66 58
 }

+ 12 - 11
src/app/views/new-statistics/maintenance-statistics/maintenance-statistics.component.ts

@@ -1,7 +1,6 @@
1 1
 import { ActivatedRoute, Router } from '@angular/router';
2 2
 import { Component, OnInit, OnDestroy } from "@angular/core";
3 3
 import { ToolService } from 'src/app/services/tool.service';
4
-import { SimpleReuseStrategy } from '../../../SimpleReuseStrategy';
5 4
 import { TabService } from '../services/tab.service';
6 5
 @Component({
7 6
   selector: "app-maintenance-statistics",
@@ -27,8 +26,7 @@ export class MaintenanceStatisticsComponent implements OnInit, OnDestroy {
27 26
 
28 27
   ngOnDestroy(){
29 28
     this.sessionRemove();
30
-    this.tabService.tabs = [];
31
-    SimpleReuseStrategy.deleteAllRouteCache();
29
+    this.tabService.deleteAllRouteSnapshot();
32 30
   }
33 31
 
34 32
   getMenuList(){
@@ -41,20 +39,23 @@ export class MaintenanceStatisticsComponent implements OnInit, OnDestroy {
41 39
   clickMenu(data){
42 40
     this.activeMenuId = data.id;
43 41
     this.secondMenuList = this.menuList.find(v => v.id == this.activeMenuId).childrens || [];
44
-    this.tabService.tabs = [];
45
-    SimpleReuseStrategy.deleteAllRouteCache();
46
-    this.secondMenuList.length && this.clickSecondMenu(this.secondMenuList[0]);
42
+    // this.tabService.deleteAllRouteSnapshot();
43
+    console.log(this.tabService.tabs)
44
+    let activeTab = this.tabService.tabs.find(v => v.active);
45
+    // return;
46
+    if(this.secondMenuList.length){
47
+      if(activeTab.path === `/newStatistics/${this.route.parent.snapshot.routeConfig.path}/${this.secondMenuList[0].link}`){
48
+        this.clickSecondMenu(this.secondMenuList[0]);
49
+      }else{
50
+        this.activeSecondMenuLink = activeTab.path.split('/').reverse()[0];
51
+      }
52
+    }
47 53
   }
48 54
 
49 55
   // 点击二级菜单
50 56
   activeSecondMenuLink:string;
51 57
   clickSecondMenu(data){
52 58
     this.activeSecondMenuLink = data.link;
53
-    let hasCache = SimpleReuseStrategy.cacheRouters.has(`/newStatistics/${this.route.parent.snapshot.routeConfig.path}/${this.activeSecondMenuLink}`);
54
-    console.log('tabs', this.tabService.tabs);
55
-    console.log('cacheRouters', SimpleReuseStrategy.cacheRouters);
56
-    console.log('cacheRouters', hasCache);
57
-    !hasCache && SimpleReuseStrategy.deleteRouteCache(`/newStatistics/${this.route.parent.snapshot.routeConfig.path}/${this.activeSecondMenuLink}`);
58 59
     this.router.navigate([`/newStatistics/${this.route.parent.snapshot.routeConfig.path}/${this.activeSecondMenuLink}`], { replaceUrl: true });
59 60
   }
60 61
 

+ 17 - 7
src/app/views/new-statistics/services/tab.service.ts

@@ -19,10 +19,20 @@ export class TabService {
19 19
     this.router.events
20 20
       .pipe(filter(event => event instanceof NavigationEnd))
21 21
       .subscribe((event: NavigationEnd) => {
22
-        event.urlAfterRedirects.startsWith('/newStatistics/') && this.updateTabs(event.urlAfterRedirects);
22
+      	console.log('event:', event)
23
+        if(event.urlAfterRedirects.startsWith('/newStatistics/')){
24
+          this.updateTabs(event.urlAfterRedirects);
25
+        }
23 26
       });
24 27
   }
25 28
 
29
+  public deleteAllRouteSnapshot(){
30
+    this.tabs.forEach(v => {
31
+      SimpleReuseStrategy.deleteRouteSnapshot(v.path);
32
+    })
33
+    this.tabs = [];
34
+  }
35
+
26 36
   private updateTabs(url: string) {
27 37
     const normalizedUrl = this.getNormalizedUrl(url);
28 38
     const existingTab = this.tabs.find(t => t.path === normalizedUrl);
@@ -60,7 +70,6 @@ export class TabService {
60 70
 
61 71
   closeTab(path: string): any {
62 72
     console.log('path:', path)
63
-    SimpleReuseStrategy.deleteRouteCache(path);
64 73
 
65 74
     const index = this.tabs.findIndex(t => t.path === path);
66 75
     if (index === -1) return;
@@ -84,6 +93,7 @@ export class TabService {
84 93
 
85 94
     // 执行删除
86 95
     this.tabs.splice(index, 1);
96
+    SimpleReuseStrategy.deleteRouteSnapshot(path);
87 97
 
88 98
     // 设置新激活页签
89 99
     if (newActiveTab) {
@@ -108,16 +118,16 @@ export class TabService {
108 118
 
109 119
   closeOtherTabs(keepTab: Tab): void {
110 120
     // 强制激活当前右键页签
111
-    this.tabs = this.tabs.filter(t => t.path === keepTab.path);
112
-    keepTab.active = true;
113
-    this.currentTab = keepTab;
114
-
115 121
     this.tabs.forEach(v => {
116 122
       if (v.path !== keepTab.path) {
117
-        SimpleReuseStrategy.deleteRouteCache(v.path);
123
+        SimpleReuseStrategy.deleteRouteSnapshot(v.path);
118 124
       }
119 125
     })
120 126
 
127
+    this.tabs = this.tabs.filter(t => t.path === keepTab.path);
128
+    keepTab.active = true;
129
+    this.currentTab = keepTab;
130
+
121 131
     // 触发路由跳转
122 132
     this.router.navigate([keepTab.path], {
123 133
       replaceUrl: true