Commit c666faed6691bf51918195484f22354ebcf86b8d

Authored by RuoYi
1 parent 6072239a

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

ruoyi-ui/src/layout/components/AppMain.vue
  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 }
... ...
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]
... ...
ruoyi-ui/src/layout/components/global.js 0 → 100644
  1 +import Vue from 'vue'
  2 +const global = new Vue()
  3 +export default global
... ...