Explorar el Código

修复三级菜单之间切换页面无法缓存的问题

RuoYi hace 5 años
padre
commit
b199db3822

+ 112 - 9
ruoyi-ui/src/layout/components/AppMain.vue

@@ -1,7 +1,8 @@
1
+<!-- @author ruoyi 20201128 支持三级以上菜单缓存 -->
1 2
 <template>
2 3
   <section class="app-main">
3 4
     <transition name="fade-transform" mode="out-in">
4
-      <keep-alive :include="cachedViews">
5
+      <keep-alive :max="20" :exclude="notCacheName">
5 6
         <router-view :key="key" />
6 7
       </keep-alive>
7 8
     </transition>
@@ -9,17 +10,119 @@
9 10
 </template>
10 11
 
11 12
 <script>
13
+import Global from "@/layout/components/global.js";
14
+
12 15
 export default {
13 16
   name: 'AppMain',
14 17
   computed: {
15
-    cachedViews() {
16
-      return this.$store.state.tagsView.cachedViews
18
+    notCacheName() {
19
+      var visitedViews = this.$store.state.tagsView.visitedViews;
20
+      var noCacheViews = [];
21
+      Object.keys(visitedViews).some((index) => {
22
+        if (visitedViews[index].meta.noCache) {
23
+          noCacheViews.push(visitedViews[index].name);
24
+        }
25
+      });
26
+      return noCacheViews;
17 27
     },
18 28
     key() {
19
-      return this.$route.path
20
-    }
21
-  }
22
-}
29
+      return this.$route.path;
30
+    },
31
+  },
32
+  mounted() {
33
+    // 关闭标签触发
34
+    Global.$on("removeCache", (name, view) => {
35
+      this.removeCache(name, view);
36
+    });
37
+  },
38
+  methods: {
39
+    // 获取有keep-alive子节点的Vnode
40
+    getVnode() {
41
+      // 判断子集非空
42
+      if (this.$children.length == 0) return false;
43
+      let vnode;
44
+      for (let item of this.$children) {
45
+        // 如果data中有key则代表找到了keep-alive下面的子集,这个key就是router-view上的key
46
+        if (item.$vnode.data.key) {
47
+          vnode = item.$vnode;
48
+          break;
49
+        }
50
+      }
51
+      return vnode ? vnode : false;
52
+    },
53
+    // 移除keep-alive缓存
54
+    removeCache(name, view = {}) {
55
+      let vnode = this.getVnode();
56
+      if (!vnode) return false;
57
+      let componentInstance = vnode.parent.componentInstance;
58
+      // 这个key是用来获取前缀用来后面正则匹配用的
59
+      let keyStart = vnode.key.split("/")[0];
60
+      let thisKey = `${keyStart}${view.fullPath}`;
61
+      let regKey = `${keyStart}${view.path}`;
62
+
63
+      this[name]({ componentInstance, thisKey, regKey });
64
+    },
65
+    // 移除其他
66
+    closeOthersTags({ componentInstance, thisKey }) {
67
+      Object.keys(componentInstance.cache).forEach((key, index) => {
68
+        if (key != thisKey) {
69
+          // 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断)
70
+          if (componentInstance.cache[key]) {
71
+            componentInstance.cache[key].componentInstance.$destroy();
72
+          }
73
+          // 删除缓存
74
+          delete componentInstance.cache[key];
75
+          // 移除key中对应的key
76
+          componentInstance.keys.splice(index, 1);
77
+        }
78
+      });
79
+    },
80
+    // 移除所有缓存
81
+    closeAllTags({ componentInstance }) {
82
+      // 销毁实例
83
+      Object.keys(componentInstance.cache).forEach((key) => {
84
+        if (componentInstance.cache[key]) {
85
+          componentInstance.cache[key].componentInstance.$destroy();
86
+        }
87
+      });
88
+      // 删除缓存
89
+      componentInstance.cache = {};
90
+      // 移除key中对应的key
91
+      componentInstance.keys = [];
92
+    },
93
+    // 移除单个缓存
94
+    closeSelectedTag({ componentInstance, regKey }) {
95
+      let reg = new RegExp(`^${regKey}`);
96
+      Object.keys(componentInstance.cache).forEach((key, i) => {
97
+        if (reg.test(key)) {
98
+          // 销毁实例
99
+          if (componentInstance.cache[key]) {
100
+            componentInstance.cache[key].componentInstance.$destroy();
101
+          }
102
+          // 删除缓存
103
+          delete componentInstance.cache[key];
104
+          // 移除key中对应的key
105
+          componentInstance.keys.splice(i, 1);
106
+        }
107
+      });
108
+    },
109
+    // 刷新单个缓存
110
+    refreshSelectedTag({ componentInstance, thisKey }) {
111
+      Object.keys(componentInstance.cache).forEach((key, index) => {
112
+        if (null != thisKey && key.replace("/redirect", "") == thisKey) {
113
+          // 1 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断)
114
+          if (componentInstance.cache[key]) {
115
+            componentInstance.cache[key].componentInstance.$destroy();
116
+          }
117
+          // 2 删除缓存
118
+          delete componentInstance.cache[key];
119
+          // 3 移除key中对应的key
120
+          componentInstance.keys.splice(index, 1);
121
+        }
122
+      });
123
+    },
124
+  },
125
+};
23 126
 </script>
24 127
 
25 128
 <style lang="scss" scoped>
@@ -31,7 +134,7 @@ export default {
31 134
   overflow: hidden;
32 135
 }
33 136
 
34
-.fixed-header+.app-main {
137
+.fixed-header + .app-main {
35 138
   padding-top: 50px;
36 139
 }
37 140
 
@@ -41,7 +144,7 @@ export default {
41 144
     min-height: calc(100vh - 84px);
42 145
   }
43 146
 
44
-  .fixed-header+.app-main {
147
+  .fixed-header + .app-main {
45 148
     padding-top: 84px;
46 149
   }
47 150
 }

+ 5 - 0
ruoyi-ui/src/layout/components/TagsView/index.vue

@@ -29,6 +29,7 @@
29 29
 <script>
30 30
 import ScrollPane from './ScrollPane'
31 31
 import path from 'path'
32
+import Global from "@/layout/components/global.js";
32 33
 
33 34
 export default {
34 35
   components: { ScrollPane },
@@ -144,6 +145,7 @@ export default {
144 145
           })
145 146
         })
146 147
       })
148
+      Global.$emit("removeCache", "refreshSelectedTag", this.selectedTag);
147 149
     },
148 150
     closeSelectedTag(view) {
149 151
       this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
@@ -151,12 +153,14 @@ export default {
151 153
           this.toLastView(visitedViews, view)
152 154
         }
153 155
       })
156
+      Global.$emit("removeCache", "closeSelectedTag", view);
154 157
     },
155 158
     closeOthersTags() {
156 159
       this.$router.push(this.selectedTag)
157 160
       this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
158 161
         this.moveToCurrentTag()
159 162
       })
163
+      Global.$emit("removeCache", "closeOthersTags", this.selectedTag);
160 164
     },
161 165
     closeAllTags(view) {
162 166
       this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
@@ -165,6 +169,7 @@ export default {
165 169
         }
166 170
         this.toLastView(visitedViews, view)
167 171
       })
172
+      Global.$emit("removeCache", "closeAllTags");
168 173
     },
169 174
     toLastView(visitedViews, view) {
170 175
       const latestView = visitedViews.slice(-1)[0]

+ 3 - 0
ruoyi-ui/src/layout/components/global.js

@@ -0,0 +1,3 @@
1
+import Vue from 'vue'
2
+const global = new Vue()
3
+export default global