From 5a333faa2b1dd349a79edea5020579c7e3922a24 Mon Sep 17 00:00:00 2001
From: chenghongxing <1126263215@qq.com>
Date: Sun, 6 Dec 2020 14:49:25 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E5=A2=9E=E5=8A=A0?=
 =?UTF-8?q?=E5=A4=9A=E9=A1=B5=E7=AD=BE=E6=A8=A1=E5=BC=8F=E4=B8=8B=E9=85=8D?=
 =?UTF-8?q?=E7=BD=AE=E6=98=AF=E5=90=A6=E7=BC=93=E5=AD=98=E9=A1=B5=E9=9D=A2?=
 =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=9B:star:=20#154=20feat:=20add?=
 =?UTF-8?q?=20the=20function=20to=20configure=20whether=20to=20cache=20pag?=
 =?UTF-8?q?es=20in=20multi=20tab=20mode;?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/components/cache/AKeepAlive.js   | 35 +++++++++++++++++++++++-----
 src/config/default/setting.config.js |  1 +
 src/layouts/tabs/TabsView.vue        | 25 ++++++++++++++++----
 src/router/config.js                 |  3 +++
 4 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/src/components/cache/AKeepAlive.js b/src/components/cache/AKeepAlive.js
index 23f0031..b04660a 100644
--- a/src/components/cache/AKeepAlive.js
+++ b/src/components/cache/AKeepAlive.js
@@ -4,7 +4,16 @@ const patternTypes = [String, RegExp, Array]
 
 function matches (pattern, name) {
   if (Array.isArray(pattern)) {
-    return pattern.indexOf(name) > -1
+    if (pattern.indexOf(name) > -1) {
+      return true
+    } else {
+      for (let item of pattern) {
+        if (isRegExp(item) && item.test(name)) {
+          return true
+        }
+      }
+      return false
+    }
   } else if (typeof pattern === 'string') {
     return pattern.split(',').indexOf(name) > -1
   } else if (isRegExp(pattern)) {
@@ -18,6 +27,13 @@ function getComponentName (opts) {
   return opts && (opts.Ctor.options.name || opts.tag)
 }
 
+function getComponentKey (vnode) {
+  const {componentOptions, key} = vnode
+  return key == null
+    ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
+    : key + componentOptions.Ctor.cid
+}
+
 function getFirstComponentChild (children) {
   if (Array.isArray(children)) {
     for (let i = 0; i < children.length; i++) {
@@ -35,7 +51,8 @@ function pruneCache (keepAliveInstance, filter) {
     const cachedNode = cache[key]
     if (cachedNode) {
       const name = getComponentName(cachedNode.componentOptions)
-      if (name && !filter(name)) {
+      const componentKey = getComponentKey(cachedNode)
+      if (name && !filter(name, componentKey)) {
         pruneCacheEntry(cache, key, keys, _vnode)
       }
     }
@@ -70,6 +87,7 @@ export default {
   props: {
     include: patternTypes,
     exclude: patternTypes,
+    excludeKeys: patternTypes,
     max: [String, Number],
     clearCaches: Array
   },
@@ -98,10 +116,13 @@ export default {
 
   mounted () {
     this.$watch('include', val => {
-      pruneCache(this, name => matches(val, name))
+      pruneCache(this, (name) => matches(val, name))
     })
     this.$watch('exclude', val => {
-      pruneCache(this, name => !matches(val, name))
+      pruneCache(this, (name) => !matches(val, name))
+    })
+    this.$watch('excludeKeys', val => {
+      pruneCache(this, (name, key) => !matches(val, key))
     })
   },
 
@@ -112,12 +133,14 @@ export default {
     if (componentOptions) {
       // check pattern
       const name = getComponentName(componentOptions)
-      const { include, exclude } = this
+      const componentKey = getComponentKey(vnode)
+      const { include, exclude, excludeKeys } = this
       if (
         // not included
         (include && (!name || !matches(include, name))) ||
         // excluded
-        (exclude && name && matches(exclude, name))
+        (exclude && name && matches(exclude, name)) ||
+        (excludeKeys && componentKey && matches(excludeKeys, componentKey))
       ) {
         return vnode
       }
diff --git a/src/config/default/setting.config.js b/src/config/default/setting.config.js
index 77dd171..19e736a 100644
--- a/src/config/default/setting.config.js
+++ b/src/config/default/setting.config.js
@@ -15,6 +15,7 @@ module.exports = {
   pageWidth: 'fixed',                   //内容区域宽度,fixed:固定宽度,fluid:流式宽度
   weekMode: false,                      //色弱模式,true:开启,false:不开启
   multiPage: false,                     //多页签模式,true:开启,false:不开启
+  cachePage: true,                      //是否缓存页面数据,仅多页签模式下生效,true 缓存, false 不缓存
   hideSetting: false,                   //隐藏设置抽屉,true:隐藏,false:不隐藏
   systemName: 'Vue Antd Admin',         //系统名称
   copyright: '2018 ICZER 工作室出品',     //copyright
diff --git a/src/layouts/tabs/TabsView.vue b/src/layouts/tabs/TabsView.vue
index 46d0430..beb8ae7 100644
--- a/src/layouts/tabs/TabsView.vue
+++ b/src/layouts/tabs/TabsView.vue
@@ -12,10 +12,10 @@
     />
     <div :class="['tabs-view-content', layout, pageWidth]" :style="`margin-top: ${multiPage ? -24 : 0}px`">
       <page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
-        <a-keep-alive v-if="multiPage" v-model="clearCaches">
+        <a-keep-alive :exclude-keys="excludeKeys" v-if="multiPage && cachePage" v-model="clearCaches">
           <router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" />
         </a-keep-alive>
-        <router-view v-else />
+        <router-view ref="tabContent" v-else-if="!refreshing" />
       </page-toggle-transition>
     </div>
   </admin-layout>
@@ -40,11 +40,12 @@ export default {
       pageList: [],
       activePage: '',
       menuVisible: false,
-      refreshing: false
+      refreshing: false,
+      excludeKeys: []
     }
   },
   computed: {
-    ...mapState('setting', ['multiPage', 'animate', 'layout', 'pageWidth']),
+    ...mapState('setting', ['multiPage', 'cachePage', 'animate', 'layout', 'pageWidth']),
     menuItemList() {
       return [
         { key: '1', icon: 'vertical-right', text: this.$t('closeLeft') },
@@ -58,6 +59,7 @@ export default {
     }
   },
   created () {
+    this.loadCacheConfig(this.$router?.options?.routes)
     this.loadCachedTabs()
     const route = this.$route
     if (this.pageList.findIndex(item => item.fullPath === route.fullPath) === -1) {
@@ -79,6 +81,10 @@ export default {
     this.correctPageMinHeight(this.tabsOffset)
   },
   watch: {
+    '$router.options.routes': function (val) {
+      this.excludeKeys = []
+      this.loadCacheConfig(val)
+    },
     '$route': function (newRoute) {
       this.activePage = newRoute.fullPath
       if (!this.multiPage) {
@@ -284,6 +290,17 @@ export default {
         }
       }
     },
+    loadCacheConfig(routes, pCache = true) {
+      routes.forEach(item => {
+        const cacheAble = item.meta?.page?.cacheAble ?? pCache ?? true
+        if (!cacheAble) {
+          this.excludeKeys.push(new RegExp(`${item.fullPath}\\d+$`))
+        }
+        if (item.children) {
+          this.loadCacheConfig(item.children, cacheAble)
+        }
+      })
+    },
     ...mapMutations('setting', ['correctPageMinHeight'])
   }
 }
diff --git a/src/router/config.js b/src/router/config.js
index 80c66d6..88a89ff 100644
--- a/src/router/config.js
+++ b/src/router/config.js
@@ -56,6 +56,9 @@ const options = {
           name: '表单页',
           meta: {
             icon: 'form',
+            page: {
+              cacheAble: false
+            }
           },
           component: PageView,
           children: [