parent
9b0428468b
commit
f754005959
@ -0,0 +1,99 @@ |
||||
import {isEmpty} from "@/utils" |
||||
|
||||
const KEY = '_routerViewKey' |
||||
|
||||
function getFirstComponentChild(children) { |
||||
if (Array.isArray(children)) { |
||||
for (const c of children) { |
||||
if (!isEmpty(c) && (!isEmpty(c.componentOptions) || c.isComment && c.asyncFactory)) { |
||||
return c |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
function getComponentName(opts) { |
||||
return opts && (opts.Ctor.options.name || opts.tag) |
||||
} |
||||
|
||||
function pruneCacheEntry(cache, key, current) { |
||||
const cached = cache[key] |
||||
if (cached && (!current || cached.tag !== current.tag)) { |
||||
cached.componentInstance && cached.componentInstance.$destroy() |
||||
} |
||||
delete cache[key] |
||||
} |
||||
|
||||
function getCacheKey(route, componentOptions) { |
||||
if (KEY in componentOptions) return componentOptions[KEY] |
||||
|
||||
const {path, meta} = route |
||||
const key = meta && meta.isDetailPage ? path : getComponentName(componentOptions) |
||||
|
||||
componentOptions[KEY] = key |
||||
|
||||
return key |
||||
} |
||||
|
||||
export default { |
||||
name: 'keep-router-view-alive', |
||||
abstract: true, |
||||
|
||||
props: {include: Array}, |
||||
|
||||
watch: { |
||||
include: { |
||||
deep: true, |
||||
handler(val) { |
||||
const {cache, $route, _vnode} = this |
||||
for (const key of Object.keys(cache)) { |
||||
const cachedNode = cache[key] |
||||
const name = getCacheKey($route, cachedNode.componentOptions) |
||||
if (name && !val.includes(name)) { |
||||
pruneCacheEntry(cache, key, _vnode) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
|
||||
created() { |
||||
this.cache = Object.create(null) |
||||
}, |
||||
|
||||
beforeDestroy() { |
||||
for (const key of Object.keys(this.cache)) { |
||||
pruneCacheEntry(this.cache, key) |
||||
} |
||||
}, |
||||
|
||||
render() { |
||||
const slot = this.$slots.default |
||||
const vnode = getFirstComponentChild(slot) |
||||
let componentOptions = vnode && vnode.componentOptions |
||||
|
||||
if (componentOptions) { |
||||
//忽略<transition/>组件
|
||||
const child = componentOptions.tag === 'transition' ? componentOptions.children[0] : vnode |
||||
componentOptions = child && child.componentOptions |
||||
|
||||
if (componentOptions) { |
||||
const key = getCacheKey(this.$route, componentOptions) |
||||
const {include, cache} = this |
||||
|
||||
if (include && !include.includes(key)) { |
||||
return vnode |
||||
} |
||||
|
||||
if (cache[key]) { |
||||
child.componentInstance = cache[key].componentInstance |
||||
} |
||||
else cache[key] = child |
||||
|
||||
child.data.keepAlive = true |
||||
} |
||||
} |
||||
|
||||
return vnode || (slot && slot[0]) |
||||
} |
||||
} |
||||
@ -1,16 +1,16 @@ |
||||
import {leftSideRouteTransition, rightSideRouteTransition} from '@/config' |
||||
import {leftSideRouteTransition as left, rightSideRouteTransition as right} from '@/config' |
||||
|
||||
export default { |
||||
methods: { |
||||
//根据访问的tab页的左右顺序来确定路由动画
|
||||
decideRouteTransition(to, from) { |
||||
let fromIndex = this.visitedViews.findIndex(i => i.path === from.path) |
||||
if (fromIndex < 0) return this.$store.commit('tagsView/transitionName', rightSideRouteTransition) |
||||
let transitionName = right |
||||
|
||||
let toIndex = this.visitedViews.findIndex(i => i.path === to.path) |
||||
if (toIndex < 0) return this.$store.commit('tagsView/transitionName', rightSideRouteTransition) |
||||
const fromIndex = this.visitedViews.findIndex(i => i.path === from.path) |
||||
const toIndex = this.visitedViews.findIndex(i => i.path === to.path) |
||||
if (fromIndex < toIndex) transitionName = left |
||||
|
||||
this.$store.commit('tagsView/transitionName', toIndex > fromIndex ? rightSideRouteTransition : leftSideRouteTransition) |
||||
this.$store.commit('tagsView/transitionName', transitionName) |
||||
}, |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,17 @@ |
||||
<template> |
||||
<div> |
||||
<div class="tip-row">详情页缓存示例</div> |
||||
<el-input v-model="data"/> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
name: "detailPage", |
||||
data() { |
||||
return { |
||||
data: '' |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
Loading…
Reference in new issue