AppMain.vue 4.8 KB

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