33import { isRegExp , remove } from 'shared/util'
44import { getFirstComponentChild } from 'core/vdom/helpers/index'
55
6- type VNodeCache = { [ key : string ] : ?VNode } ;
6+ type CacheEntry = {
7+ name : ?string ;
8+ tag: ?string ;
9+ componentInstance: Component ;
10+ } ;
11+
12+ type CacheEntryMap = { [ key : string ] : ?CacheEntry } ;
713
814function getComponentName ( opts : ?VNodeComponentOptions ) : ?string {
915 return opts && ( opts . Ctor . options . name || opts . tag )
@@ -24,9 +30,9 @@ function matches (pattern: string | RegExp | Array<string>, name: string): boole
2430function pruneCache ( keepAliveInstance : any , filter : Function ) {
2531 const { cache, keys, _vnode } = keepAliveInstance
2632 for ( const key in cache ) {
27- const cachedNode : ?VNode = cache [ key ]
28- if ( cachedNode ) {
29- const name : ?string = getComponentName ( cachedNode . componentOptions )
33+ const entry : ?CacheEntry = cache [ key ]
34+ if ( entry ) {
35+ const name : ?string = entry . name
3036 if ( name && ! filter ( name ) ) {
3137 pruneCacheEntry ( cache , key , keys , _vnode )
3238 }
@@ -35,14 +41,14 @@ function pruneCache (keepAliveInstance: any, filter: Function) {
3541}
3642
3743function pruneCacheEntry (
38- cache : VNodeCache ,
44+ cache : CacheEntryMap ,
3945 key : string ,
4046 keys : Array < string > ,
4147 current ?: VNode
4248) {
43- const cached = cache [ key ]
44- if ( cached && ( ! current || cached . tag !== current . tag ) ) {
45- cached . componentInstance . $destroy ( )
49+ const entry : ? CacheEntry = cache [ key ]
50+ if ( entry && ( ! current || entry . tag !== current . tag ) ) {
51+ entry . componentInstance . $destroy ( )
4652 }
4753 cache [ key ] = null
4854 remove ( keys , key )
@@ -60,6 +66,26 @@ export default {
6066 max : [ String , Number ]
6167 } ,
6268
69+ methods : {
70+ cacheVNode ( ) {
71+ const { cache, keys, vnodeToCache, keyToCache } = this
72+ if ( vnodeToCache ) {
73+ const { tag, componentInstance, componentOptions } = vnodeToCache
74+ cache [ keyToCache ] = {
75+ name : getComponentName ( componentOptions ) ,
76+ tag,
77+ componentInstance,
78+ }
79+ keys . push ( keyToCache )
80+ // prune oldest entry
81+ if ( this . max && keys . length > parseInt ( this . max ) ) {
82+ pruneCacheEntry ( cache , keys [ 0 ] , keys , this . _vnode )
83+ }
84+ this . vnodeToCache = null
85+ }
86+ }
87+ } ,
88+
6389 created ( ) {
6490 this . cache = Object . create ( null )
6591 this . keys = [ ]
@@ -72,6 +98,7 @@ export default {
7298 } ,
7399
74100 mounted ( ) {
101+ this . cacheVNode ( )
75102 this . $watch ( 'include' , val => {
76103 pruneCache ( this , name => matches ( val , name ) )
77104 } )
@@ -80,6 +107,10 @@ export default {
80107 } )
81108 } ,
82109
110+ updated () {
111+ this . cacheVNode ( )
112+ } ,
113+
83114 render () {
84115 const slot = this . $slots . default
85116 const vnode : VNode = getFirstComponentChild ( slot )
@@ -109,12 +140,9 @@ export default {
109140 remove ( keys , key )
110141 keys . push ( key )
111142 } else {
112- cache [ key ] = vnode
113- keys . push ( key )
114- // prune oldest entry
115- if ( this . max && keys . length > parseInt ( this . max ) ) {
116- pruneCacheEntry ( cache , keys [ 0 ] , keys , this . _vnode )
117- }
143+ // delay setting the cache until update
144+ this . vnodeToCache = vnode
145+ this . keyToCache = key
118146 }
119147
120148 vnode.data.keepAlive = true
0 commit comments