Merge 9c73f6b310 into 33a93a12b4
				
					
				
			This commit is contained in:
		
							
								
								
									
										94
									
								
								src/components/V/v-keep-alive.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/components/V/v-keep-alive.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | |||||||
|  | <script> | ||||||
|  | /** 通过URL 缓存页面 | ||||||
|  |  *  日期:2020/8/4 | ||||||
|  |  */ | ||||||
|  | var cache = Object.create(null) | ||||||
|  | var keys = [] | ||||||
|  | function remove(keys, key) { | ||||||
|  |   if (keys && key) { | ||||||
|  |     var index = keys.indexOf(key) | ||||||
|  |     if (index !== -1) { | ||||||
|  |       keys.splice(index, 1) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | /** | ||||||
|  |  * 修剪缓存 | ||||||
|  |  */ | ||||||
|  | function pruneCache(keepAliveInstance, filter) { | ||||||
|  |   const { cache, keys, _vnode } = keepAliveInstance | ||||||
|  |   for (const key in cache) { | ||||||
|  |     const cachedNode = cache[key] | ||||||
|  |     if (cachedNode) { | ||||||
|  |       if (!filter(key)) { | ||||||
|  |         pruneCacheEntry(cache, key, keys, _vnode) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | /** | ||||||
|  |  * 修剪缓存入口 | ||||||
|  |  */ | ||||||
|  | function pruneCacheEntry(cache, key, keys, current) { | ||||||
|  |   const cached = cache[key] | ||||||
|  |   // 主动执行某个组件的destory,触发destroy钩子,达到销毁目的,然后移除缓存中的key-value | ||||||
|  |   cached && cached.componentInstance.$destroy() | ||||||
|  |   cache[key] = null | ||||||
|  |   remove(keys, key) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   name: 'VKeepAlive', | ||||||
|  |   // 抽象组件 | ||||||
|  |   abstract: true, | ||||||
|  |   props: { | ||||||
|  |     keyarray: { | ||||||
|  |       type: Array, | ||||||
|  |       default: function() { | ||||||
|  |         return [] | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   created() { | ||||||
|  |     // 组件创建时创建缓存对象 | ||||||
|  |     this.cache = cache | ||||||
|  |     this.keys = keys | ||||||
|  |   }, | ||||||
|  |   mounted() { | ||||||
|  |     this.$watch('keyarray', val => { | ||||||
|  |       // 销毁不在key数组的对象 | ||||||
|  |       pruneCache(this, name => val.some(v => v === name)) | ||||||
|  |     }) | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   render() { | ||||||
|  |     const slot = this.$slots.default | ||||||
|  |     const vnode = slot[0] | ||||||
|  |     const componentOptions = vnode && vnode.componentOptions | ||||||
|  |     this.$vnode.componentOptions.Ctor.options.abstract = true | ||||||
|  |     if (componentOptions) { | ||||||
|  |       const { cache, keys } = this | ||||||
|  |       const key = | ||||||
|  |         vnode.key.indexOf('__transition') === 0 ? vnode.data.key : vnode.key | ||||||
|  |       var isCache = | ||||||
|  |         this.keyarray.filter(v => { | ||||||
|  |           return v === key | ||||||
|  |         }).length === 0 | ||||||
|  |       if (isCache) { | ||||||
|  |         vnode.data.keepAlive = false | ||||||
|  |       } else { | ||||||
|  |         if (cache[key]) { | ||||||
|  |           vnode.componentInstance = cache[key].componentInstance | ||||||
|  |           remove(keys, key) | ||||||
|  |           keys.push(key) | ||||||
|  |         } else { | ||||||
|  |           cache[key] = vnode | ||||||
|  |           keys.push(key) | ||||||
|  |         } | ||||||
|  |         vnode.data.keepAlive = true | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return vnode || (slot && slot[0]) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </script> | ||||||
| @@ -1,22 +1,26 @@ | |||||||
| <template> | <template> | ||||||
|   <section class="app-main"> |   <section class="app-main"> | ||||||
|     <transition name="fade-transform" mode="out-in"> |     <transition name="fade-transform" mode="out-in"> | ||||||
|       <keep-alive :include="cachedViews"> |       <v-keep-alive :keyarray="cachedViews"> | ||||||
|         <router-view :key="key" /> |         <router-view :key="key" /> | ||||||
|       </keep-alive> |       </v-keep-alive> | ||||||
|     </transition> |     </transition> | ||||||
|   </section> |   </section> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
|  | import vKeepAlive from '../../components/V/v-keep-alive' | ||||||
| export default { | export default { | ||||||
|   name: 'AppMain', |   name: 'AppMain', | ||||||
|  |   components: { | ||||||
|  |     vKeepAlive | ||||||
|  |   }, | ||||||
|   computed: { |   computed: { | ||||||
|     cachedViews() { |     cachedViews() { | ||||||
|       return this.$store.state.tagsView.cachedViews |       return this.$store.state.tagsView.cachedViews | ||||||
|     }, |     }, | ||||||
|     key() { |     key() { | ||||||
|       return this.$route.path |       return this.$route.fullPath | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -31,7 +35,7 @@ export default { | |||||||
|   overflow: hidden; |   overflow: hidden; | ||||||
| } | } | ||||||
|  |  | ||||||
| .fixed-header+.app-main { | .fixed-header + .app-main { | ||||||
|   padding-top: 50px; |   padding-top: 50px; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -41,7 +45,7 @@ export default { | |||||||
|     min-height: calc(100vh - 84px); |     min-height: calc(100vh - 84px); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .fixed-header+.app-main { |   .fixed-header + .app-main { | ||||||
|     padding-top: 84px; |     padding-top: 84px; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|       <router-link |       <router-link | ||||||
|         v-for="tag in visitedViews" |         v-for="tag in visitedViews" | ||||||
|         ref="tag" |         ref="tag" | ||||||
|         :key="tag.path" |         :key="tag.fullPath" | ||||||
|         :class="isActive(tag)?'active':''" |         :class="isActive(tag)?'active':''" | ||||||
|         :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }" |         :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }" | ||||||
|         tag="span" |         tag="span" | ||||||
| @@ -67,7 +67,7 @@ export default { | |||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     isActive(route) { |     isActive(route) { | ||||||
|       return route.path === this.$route.path |       return route.fullPath === this.$route.fullPath | ||||||
|     }, |     }, | ||||||
|     isAffix(tag) { |     isAffix(tag) { | ||||||
|       return tag.meta && tag.meta.affix |       return tag.meta && tag.meta.affix | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ const state = { | |||||||
|  |  | ||||||
| const mutations = { | const mutations = { | ||||||
|   ADD_VISITED_VIEW: (state, view) => { |   ADD_VISITED_VIEW: (state, view) => { | ||||||
|     if (state.visitedViews.some(v => v.path === view.path)) return |     if (state.visitedViews.some(v => v.fullPath === view.fullPath)) return | ||||||
|     state.visitedViews.push( |     state.visitedViews.push( | ||||||
|       Object.assign({}, view, { |       Object.assign({}, view, { | ||||||
|         title: view.meta.title || 'no-name' |         title: view.meta.title || 'no-name' | ||||||
| @@ -13,32 +13,32 @@ const mutations = { | |||||||
|     ) |     ) | ||||||
|   }, |   }, | ||||||
|   ADD_CACHED_VIEW: (state, view) => { |   ADD_CACHED_VIEW: (state, view) => { | ||||||
|     if (state.cachedViews.includes(view.name)) return |     if (state.cachedViews.includes(view.fullPath)) return | ||||||
|     if (!view.meta.noCache) { |     if (!view.meta.noCache) { | ||||||
|       state.cachedViews.push(view.name) |       state.cachedViews.push(view.fullPath) | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   DEL_VISITED_VIEW: (state, view) => { |   DEL_VISITED_VIEW: (state, view) => { | ||||||
|     for (const [i, v] of state.visitedViews.entries()) { |     for (const [i, v] of state.visitedViews.entries()) { | ||||||
|       if (v.path === view.path) { |       if (v.fullPath === view.fullPath) { | ||||||
|         state.visitedViews.splice(i, 1) |         state.visitedViews.splice(i, 1) | ||||||
|         break |         break | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   DEL_CACHED_VIEW: (state, view) => { |   DEL_CACHED_VIEW: (state, view) => { | ||||||
|     const index = state.cachedViews.indexOf(view.name) |     const index = state.cachedViews.indexOf(view.fullPath) | ||||||
|     index > -1 && state.cachedViews.splice(index, 1) |     index > -1 && state.cachedViews.splice(index, 1) | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   DEL_OTHERS_VISITED_VIEWS: (state, view) => { |   DEL_OTHERS_VISITED_VIEWS: (state, view) => { | ||||||
|     state.visitedViews = state.visitedViews.filter(v => { |     state.visitedViews = state.visitedViews.filter(v => { | ||||||
|       return v.meta.affix || v.path === view.path |       return v.meta.affix || v.fullPath === view.fullPath | ||||||
|     }) |     }) | ||||||
|   }, |   }, | ||||||
|   DEL_OTHERS_CACHED_VIEWS: (state, view) => { |   DEL_OTHERS_CACHED_VIEWS: (state, view) => { | ||||||
|     const index = state.cachedViews.indexOf(view.name) |     const index = state.cachedViews.indexOf(view.fullPath) | ||||||
|     if (index > -1) { |     if (index > -1) { | ||||||
|       state.cachedViews = state.cachedViews.slice(index, index + 1) |       state.cachedViews = state.cachedViews.slice(index, index + 1) | ||||||
|     } else { |     } else { | ||||||
| @@ -58,7 +58,7 @@ const mutations = { | |||||||
|  |  | ||||||
|   UPDATE_VISITED_VIEW: (state, view) => { |   UPDATE_VISITED_VIEW: (state, view) => { | ||||||
|     for (let v of state.visitedViews) { |     for (let v of state.visitedViews) { | ||||||
|       if (v.path === view.path) { |       if (v.fullPath === view.fullPath) { | ||||||
|         v = Object.assign(v, view) |         v = Object.assign(v, view) | ||||||
|         break |         break | ||||||
|       } |       } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user