|
|
@@ -3,7 +3,13 @@
|
|
|
import { isRegExp, remove } from 'shared/util'
|
|
|
import { getFirstComponentChild } from 'core/vdom/helpers/index'
|
|
|
|
|
|
-type VNodeCache = { [key: string]: ?VNode };
|
|
|
+type CacheEntry = {
|
|
|
+ name: ?string;
|
|
|
+ tag: ?string;
|
|
|
+ componentInstance: Component;
|
|
|
+};
|
|
|
+
|
|
|
+type CacheEntryMap = { [key: string]: ?CacheEntry };
|
|
|
|
|
|
function getComponentName (opts: ?VNodeComponentOptions): ?string {
|
|
|
return opts && (opts.Ctor.options.name || opts.tag)
|
|
|
@@ -24,9 +30,9 @@ function matches (pattern: string | RegExp | Array<string>, name: string): boole
|
|
|
function pruneCache (keepAliveInstance: any, filter: Function) {
|
|
|
const { cache, keys, _vnode } = keepAliveInstance
|
|
|
for (const key in cache) {
|
|
|
- const cachedNode: ?VNode = cache[key]
|
|
|
- if (cachedNode) {
|
|
|
- const name: ?string = getComponentName(cachedNode.componentOptions)
|
|
|
+ const entry: ?CacheEntry = cache[key]
|
|
|
+ if (entry) {
|
|
|
+ const name: ?string = entry.name
|
|
|
if (name && !filter(name)) {
|
|
|
pruneCacheEntry(cache, key, keys, _vnode)
|
|
|
}
|
|
|
@@ -35,14 +41,14 @@ function pruneCache (keepAliveInstance: any, filter: Function) {
|
|
|
}
|
|
|
|
|
|
function pruneCacheEntry (
|
|
|
- cache: VNodeCache,
|
|
|
+ cache: CacheEntryMap,
|
|
|
key: string,
|
|
|
keys: Array<string>,
|
|
|
current?: VNode
|
|
|
) {
|
|
|
- const cached = cache[key]
|
|
|
- if (cached && (!current || cached.tag !== current.tag)) {
|
|
|
- cached.componentInstance.$destroy()
|
|
|
+ const entry: ?CacheEntry = cache[key]
|
|
|
+ if (entry && (!current || entry.tag !== current.tag)) {
|
|
|
+ entry.componentInstance.$destroy()
|
|
|
}
|
|
|
cache[key] = null
|
|
|
remove(keys, key)
|
|
|
@@ -60,6 +66,26 @@ export default {
|
|
|
max: [String, Number]
|
|
|
},
|
|
|
|
|
|
+ methods: {
|
|
|
+ cacheVNode() {
|
|
|
+ const { cache, keys, vnodeToCache, keyToCache } = this
|
|
|
+ if (vnodeToCache) {
|
|
|
+ const { tag, componentInstance, componentOptions } = vnodeToCache
|
|
|
+ cache[keyToCache] = {
|
|
|
+ name: getComponentName(componentOptions),
|
|
|
+ tag,
|
|
|
+ componentInstance,
|
|
|
+ }
|
|
|
+ keys.push(keyToCache)
|
|
|
+ // prune oldest entry
|
|
|
+ if (this.max && keys.length > parseInt(this.max)) {
|
|
|
+ pruneCacheEntry(cache, keys[0], keys, this._vnode)
|
|
|
+ }
|
|
|
+ this.vnodeToCache = null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
created () {
|
|
|
this.cache = Object.create(null)
|
|
|
this.keys = []
|
|
|
@@ -72,6 +98,7 @@ export default {
|
|
|
},
|
|
|
|
|
|
mounted () {
|
|
|
+ this.cacheVNode()
|
|
|
this.$watch('include', val => {
|
|
|
pruneCache(this, name => matches(val, name))
|
|
|
})
|
|
|
@@ -80,6 +107,10 @@ export default {
|
|
|
})
|
|
|
},
|
|
|
|
|
|
+ updated () {
|
|
|
+ this.cacheVNode()
|
|
|
+ },
|
|
|
+
|
|
|
render () {
|
|
|
const slot = this.$slots.default
|
|
|
const vnode: VNode = getFirstComponentChild(slot)
|
|
|
@@ -109,12 +140,9 @@ export default {
|
|
|
remove(keys, key)
|
|
|
keys.push(key)
|
|
|
} else {
|
|
|
- cache[key] = vnode
|
|
|
- keys.push(key)
|
|
|
- // prune oldest entry
|
|
|
- if (this.max && keys.length > parseInt(this.max)) {
|
|
|
- pruneCacheEntry(cache, keys[0], keys, this._vnode)
|
|
|
- }
|
|
|
+ // delay setting the cache until update
|
|
|
+ this.vnodeToCache = vnode
|
|
|
+ this.keyToCache = key
|
|
|
}
|
|
|
|
|
|
vnode.data.keepAlive = true
|