3
3
import { isRegExp , remove } from 'shared/util'
4
4
import { getFirstComponentChild } from 'core/vdom/helpers/index'
5
5
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 } ;
7
13
8
14
function getComponentName ( opts : ?VNodeComponentOptions ) : ?string {
9
15
return opts && ( opts . Ctor . options . name || opts . tag )
@@ -24,9 +30,9 @@ function matches (pattern: string | RegExp | Array<string>, name: string): boole
24
30
function pruneCache ( keepAliveInstance : any , filter : Function ) {
25
31
const { cache, keys, _vnode } = keepAliveInstance
26
32
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
30
36
if ( name && ! filter ( name ) ) {
31
37
pruneCacheEntry ( cache , key , keys , _vnode )
32
38
}
@@ -35,14 +41,14 @@ function pruneCache (keepAliveInstance: any, filter: Function) {
35
41
}
36
42
37
43
function pruneCacheEntry (
38
- cache : VNodeCache ,
44
+ cache : CacheEntryMap ,
39
45
key : string ,
40
46
keys : Array < string > ,
41
47
current ?: VNode
42
48
) {
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 ( )
46
52
}
47
53
cache [ key ] = null
48
54
remove ( keys , key )
@@ -60,6 +66,26 @@ export default {
60
66
max : [ String , Number ]
61
67
} ,
62
68
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
+
63
89
created ( ) {
64
90
this . cache = Object . create ( null )
65
91
this . keys = [ ]
@@ -72,6 +98,7 @@ export default {
72
98
} ,
73
99
74
100
mounted ( ) {
101
+ this . cacheVNode ( )
75
102
this . $watch ( 'include' , val => {
76
103
pruneCache ( this , name => matches ( val , name ) )
77
104
} )
@@ -80,6 +107,10 @@ export default {
80
107
} )
81
108
} ,
82
109
110
+ updated () {
111
+ this . cacheVNode ( )
112
+ } ,
113
+
83
114
render () {
84
115
const slot = this . $slots . default
85
116
const vnode : VNode = getFirstComponentChild ( slot )
@@ -109,12 +140,9 @@ export default {
109
140
remove ( keys , key )
110
141
keys . push ( key )
111
142
} 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
118
146
}
119
147
120
148
vnode.data.keepAlive = true
0 commit comments