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> | ||||
|   <section class="app-main"> | ||||
|     <transition name="fade-transform" mode="out-in"> | ||||
|       <keep-alive :include="cachedViews"> | ||||
|       <v-keep-alive :keyarray="cachedViews"> | ||||
|         <router-view :key="key" /> | ||||
|       </keep-alive> | ||||
|       </v-keep-alive> | ||||
|     </transition> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import vKeepAlive from '../../components/V/v-keep-alive' | ||||
| export default { | ||||
|   name: 'AppMain', | ||||
|   components: { | ||||
|     vKeepAlive | ||||
|   }, | ||||
|   computed: { | ||||
|     cachedViews() { | ||||
|       return this.$store.state.tagsView.cachedViews | ||||
|     }, | ||||
|     key() { | ||||
|       return this.$route.path | ||||
|       return this.$route.fullPath | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -31,7 +35,7 @@ export default { | ||||
|   overflow: hidden; | ||||
| } | ||||
|  | ||||
| .fixed-header+.app-main { | ||||
| .fixed-header + .app-main { | ||||
|   padding-top: 50px; | ||||
| } | ||||
|  | ||||
| @@ -41,7 +45,7 @@ export default { | ||||
|     min-height: calc(100vh - 84px); | ||||
|   } | ||||
|  | ||||
|   .fixed-header+.app-main { | ||||
|   .fixed-header + .app-main { | ||||
|     padding-top: 84px; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
|       <router-link | ||||
|         v-for="tag in visitedViews" | ||||
|         ref="tag" | ||||
|         :key="tag.path" | ||||
|         :key="tag.fullPath" | ||||
|         :class="isActive(tag)?'active':''" | ||||
|         :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }" | ||||
|         tag="span" | ||||
| @@ -67,7 +67,7 @@ export default { | ||||
|   }, | ||||
|   methods: { | ||||
|     isActive(route) { | ||||
|       return route.path === this.$route.path | ||||
|       return route.fullPath === this.$route.fullPath | ||||
|     }, | ||||
|     isAffix(tag) { | ||||
|       return tag.meta && tag.meta.affix | ||||
|   | ||||
| @@ -5,7 +5,7 @@ const state = { | ||||
|  | ||||
| const mutations = { | ||||
|   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( | ||||
|       Object.assign({}, view, { | ||||
|         title: view.meta.title || 'no-name' | ||||
| @@ -13,32 +13,32 @@ const mutations = { | ||||
|     ) | ||||
|   }, | ||||
|   ADD_CACHED_VIEW: (state, view) => { | ||||
|     if (state.cachedViews.includes(view.name)) return | ||||
|     if (state.cachedViews.includes(view.fullPath)) return | ||||
|     if (!view.meta.noCache) { | ||||
|       state.cachedViews.push(view.name) | ||||
|       state.cachedViews.push(view.fullPath) | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   DEL_VISITED_VIEW: (state, view) => { | ||||
|     for (const [i, v] of state.visitedViews.entries()) { | ||||
|       if (v.path === view.path) { | ||||
|       if (v.fullPath === view.fullPath) { | ||||
|         state.visitedViews.splice(i, 1) | ||||
|         break | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   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) | ||||
|   }, | ||||
|  | ||||
|   DEL_OTHERS_VISITED_VIEWS: (state, view) => { | ||||
|     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) => { | ||||
|     const index = state.cachedViews.indexOf(view.name) | ||||
|     const index = state.cachedViews.indexOf(view.fullPath) | ||||
|     if (index > -1) { | ||||
|       state.cachedViews = state.cachedViews.slice(index, index + 1) | ||||
|     } else { | ||||
| @@ -58,7 +58,7 @@ const mutations = { | ||||
|  | ||||
|   UPDATE_VISITED_VIEW: (state, view) => { | ||||
|     for (let v of state.visitedViews) { | ||||
|       if (v.path === view.path) { | ||||
|       if (v.fullPath === view.fullPath) { | ||||
|         v = Object.assign(v, view) | ||||
|         break | ||||
|       } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user