@@ -5,6 +5,10 @@ import { getFirstComponentChild } from 'core/vdom/helpers/index'
5
5
6
6
const patternTypes = [ String , RegExp ]
7
7
8
+ function getComponentName ( opts : ?VNodeComponentOptions ) : ?string {
9
+ return opts && ( opts . Ctor . options . name || opts . tag )
10
+ }
11
+
8
12
function matches ( pattern : string | RegExp , name : string ) : boolean {
9
13
if ( typeof pattern === 'string' ) {
10
14
return pattern . split ( ',' ) . indexOf ( name ) > - 1
@@ -13,22 +17,62 @@ function matches (pattern: string | RegExp, name: string): boolean {
13
17
}
14
18
}
15
19
20
+ function pruneCache ( cache , filter ) {
21
+ for ( const key in cache ) {
22
+ const cachedNode = cache [ key ]
23
+ if ( cachedNode ) {
24
+ const name = getComponentName ( cachedNode . componentOptions )
25
+ if ( name && ! filter ( name ) ) {
26
+ pruneCacheEntry ( cachedNode )
27
+ cache [ key ] = null
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ function pruneCacheEntry ( vnode : ?MountedComponentVNode ) {
34
+ if ( vnode ) {
35
+ if ( ! vnode . componentInstance . _inactive ) {
36
+ callHook ( vnode . componentInstance , 'deactivated' )
37
+ }
38
+ vnode . componentInstance . $destroy ( )
39
+ }
40
+ }
41
+
16
42
export default {
17
43
name : 'keep-alive' ,
18
44
abstract : true ,
45
+
19
46
props : {
20
47
include : patternTypes ,
21
48
exclude : patternTypes
22
49
} ,
50
+
23
51
created ( ) {
24
52
this . cache = Object . create ( null )
25
53
} ,
54
+
55
+ destroyed ( ) {
56
+ for ( const key in this . cache ) {
57
+ pruneCacheEntry ( this . cache [ key ] )
58
+ }
59
+ } ,
60
+
61
+ watch : {
62
+ include ( val : string | RegExp ) {
63
+ pruneCache ( this . cache , name => matches ( val , name ) )
64
+ } ,
65
+ exclude ( val : string | RegExp ) {
66
+ pruneCache ( this . cache , name => ! matches ( val , name ) )
67
+ }
68
+ } ,
69
+
26
70
render ( ) {
27
71
const vnode : VNode = getFirstComponentChild ( this . $slots . default )
28
- if ( vnode && vnode . componentOptions ) {
29
- const opts : VNodeComponentOptions = vnode . componentOptions
72
+ const componentOptions = vnode && vnode . componentOptions
73
+ if ( componentOptions ) {
30
74
// check pattern
31
- const name = opts . Ctor . options . name || opts . tag
75
+ const name = getComponentName ( componentOptions )
32
76
if ( name && (
33
77
( this . include && ! matches ( this . include , name ) ) ||
34
78
( this . exclude && matches ( this . exclude , name ) )
@@ -38,7 +82,7 @@ export default {
38
82
const key = vnode . key == null
39
83
// same constructor may get registered as different local components
40
84
// so cid alone is not enough (#3269)
41
- ? opts . Ctor . cid + ( opts . tag ? `::${ opts . tag } ` : '' )
85
+ ? componentOptions . Ctor . cid + ( componentOptions . tag ? `::${ componentOptions . tag } ` : '' )
42
86
: vnode . key
43
87
if ( this . cache [ key ] ) {
44
88
vnode . componentInstance = this . cache [ key ] . componentInstance
@@ -48,12 +92,5 @@ export default {
48
92
vnode . data . keepAlive = true
49
93
}
50
94
return vnode
51
- } ,
52
- destroyed ( ) {
53
- for ( const key in this . cache ) {
54
- const vnode = this . cache [ key ]
55
- callHook ( vnode . componentInstance , 'deactivated' )
56
- vnode . componentInstance . $destroy ( )
57
- }
58
95
}
59
96
}
0 commit comments