@@ -5,6 +5,10 @@ import { getFirstComponentChild } from 'core/vdom/helpers/index'
55
66const patternTypes = [ String , RegExp ]
77
8+ function getComponentName ( opts : ?VNodeComponentOptions ) : ?string {
9+ return opts && ( opts . Ctor . options . name || opts . tag )
10+ }
11+
812function matches ( pattern : string | RegExp , name : string ) : boolean {
913 if ( typeof pattern === 'string' ) {
1014 return pattern . split ( ',' ) . indexOf ( name ) > - 1
@@ -13,22 +17,62 @@ function matches (pattern: string | RegExp, name: string): boolean {
1317 }
1418}
1519
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+
1642export default {
1743 name : 'keep-alive' ,
1844 abstract : true ,
45+
1946 props : {
2047 include : patternTypes ,
2148 exclude : patternTypes
2249 } ,
50+
2351 created ( ) {
2452 this . cache = Object . create ( null )
2553 } ,
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+
2670 render ( ) {
2771 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 ) {
3074 // check pattern
31- const name = opts . Ctor . options . name || opts . tag
75+ const name = getComponentName ( componentOptions )
3276 if ( name && (
3377 ( this . include && ! matches ( this . include , name ) ) ||
3478 ( this . exclude && matches ( this . exclude , name ) )
@@ -38,7 +82,7 @@ export default {
3882 const key = vnode . key == null
3983 // same constructor may get registered as different local components
4084 // so cid alone is not enough (#3269)
41- ? opts . Ctor . cid + ( opts . tag ? `::${ opts . tag } ` : '' )
85+ ? componentOptions . Ctor . cid + ( componentOptions . tag ? `::${ componentOptions . tag } ` : '' )
4286 : vnode . key
4387 if ( this . cache [ key ] ) {
4488 vnode . componentInstance = this . cache [ key ] . componentInstance
@@ -48,12 +92,5 @@ export default {
4892 vnode . data . keepAlive = true
4993 }
5094 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- }
5895 }
5996}
0 commit comments