Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
forked fromvuejs/vue

Commit2cba6d4

Browse files
committed
feat: add max prop for <keep-alive>
1 parent2503e13 commit2cba6d4

File tree

2 files changed

+103
-18
lines changed

2 files changed

+103
-18
lines changed

‎src/core/components/keep-alive.js

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
/*@flow */
22

3-
import{isRegExp}from'shared/util'
3+
import{isRegExp,remove}from'shared/util'
44
import{getFirstComponentChild}from'core/vdom/helpers/index'
55

66
typeVNodeCache={[key:string]: ?VNode};
77

8-
constpatternTypes:Array<Function> = [String, RegExp, Array]
9-
108
functiongetComponentName(opts: ?VNodeComponentOptions): ?string{
119
returnopts&&(opts.Ctor.options.name||opts.tag)
1210
}
@@ -23,52 +21,62 @@ function matches (pattern: string | RegExp | Array<string>, name: string): boole
2321
returnfalse
2422
}
2523

26-
functionpruneCache(cache:VNodeCache,current:VNode,filter:Function){
24+
functionpruneCache(keepAliveInstance:any,filter:Function){
25+
const{ cache, keys, _vnode}=keepAliveInstance
2726
for(constkeyincache){
2827
constcachedNode: ?VNode=cache[key]
2928
if(cachedNode){
3029
constname: ?string=getComponentName(cachedNode.componentOptions)
3130
if(name&&!filter(name)){
32-
if(cachedNode!==current){
33-
pruneCacheEntry(cachedNode)
34-
}
35-
cache[key] = null
31+
pruneCacheEntry(cache,key,keys,_vnode)
3632
}
3733
}
3834
}
3935
}
4036

41-
functionpruneCacheEntry(vnode: ?VNode){
42-
if(vnode){
43-
vnode.componentInstance.$destroy()
37+
functionpruneCacheEntry(
38+
cache:VNodeCache,
39+
key:string,
40+
keys:Array<string>,
41+
current?:VNode
42+
){
43+
constcached=cache[key]
44+
if(cached&&cached!==current){
45+
cached.componentInstance.$destroy()
4446
}
47+
cache[key]=null
48+
remove(keys,key)
4549
}
4650

51+
constpatternTypes:Array<Function> = [String, RegExp, Array]
52+
4753
export default{
4854
name:'keep-alive',
4955
abstract:true,
5056

5157
props:{
5258
include:patternTypes,
53-
exclude:patternTypes
59+
exclude:patternTypes,
60+
max:[String,Number]
5461
},
5562

5663
created(){
5764
this.cache=Object.create(null)
65+
this.keys=[]
5866
},
5967

6068
destroyed (){
6169
for(constkeyinthis.cache){
62-
pruneCacheEntry(this.cache[key])
70+
pruneCacheEntry(this.cache,key,this.keys)
6371
}
6472
},
6573

6674
watch:{
6775
include(val:string|RegExp|Array<string>){
68-
pruneCache(this.cache,this._vnode,name=>matches(val,name))
76+
pruneCache(this,name=>matches(val,name))
6977
},
7078
exclude(val:string|RegExp|Array<string>){
71-
pruneCache(this.cache,this._vnode,name=>!matches(val,name))
79+
pruneCache(this,name=>!matches(val,name))
7280
}
7381
},
7482

@@ -84,16 +92,27 @@ export default {
8492
)){
8593
returnvnode
8694
}
95+
96+
const{cache, keys}=this
8797
constkey: ?string=vnode.key==null
8898
// same constructor may get registered as different local components
8999
// so cid alone is not enough (#3269)
90100
?componentOptions.Ctor.cid+(componentOptions.tag ?`::${componentOptions.tag}` :'')
91101
:vnode.key
92-
if(this.cache[key]){
93-
vnode.componentInstance=this.cache[key].componentInstance
102+
if(cache[key]){
103+
vnode.componentInstance=cache[key].componentInstance
104+
// make current key freshest
105+
remove(keys,key)
106+
keys.push(key)
94107
}else{
95-
this.cache[key]=vnode
108+
cache[key]=vnode
109+
keys.push(key)
110+
// prune oldest entry
111+
if(this.max&&keys.length>parseInt(this.max)){
112+
pruneCacheEntry(cache,keys[0],keys,this._vnode)
113+
}
96114
}
115+
97116
vnode.data.keepAlive = true
98117
}
99118
returnvnode

‎test/unit/features/component/component-keep-alive.spec.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,5 +946,71 @@ describe('Component keep-alive', () => {
946946
}).then(done)
947947
}
948948
})
949+
950+
it('max',done=>{
951+
constspyA=jasmine.createSpy()
952+
constspyB=jasmine.createSpy()
953+
constspyC=jasmine.createSpy()
954+
constspyAD=jasmine.createSpy()
955+
constspyBD=jasmine.createSpy()
956+
constspyCD=jasmine.createSpy()
957+
958+
functionassertCount(calls){
959+
expect([
960+
spyA.calls.count(),
961+
spyAD.calls.count(),
962+
spyB.calls.count(),
963+
spyBD.calls.count(),
964+
spyC.calls.count(),
965+
spyCD.calls.count()
966+
]).toEqual(calls)
967+
}
968+
969+
constvm=newVue({
970+
template:`
971+
<keep-alive max="2">
972+
<component :is="n"></component>
973+
</keep-alive>
974+
`,
975+
data:{
976+
n:'aa'
977+
},
978+
components:{
979+
aa:{
980+
template:'<div>a</div>',
981+
created:spyA,
982+
destroyed:spyAD
983+
},
984+
bb:{
985+
template:'<div>bbb</div>',
986+
created:spyB,
987+
destroyed:spyBD
988+
},
989+
cc:{
990+
template:'<div>ccc</div>',
991+
created:spyC,
992+
destroyed:spyCD
993+
}
994+
}
995+
}).$mount()
996+
997+
assertCount([1,0,0,0,0,0])
998+
vm.n='bb'
999+
waitForUpdate(()=>{
1000+
assertCount([1,0,1,0,0,0])
1001+
vm.n='cc'
1002+
}).then(()=>{
1003+
// should prune A because max cache reached
1004+
assertCount([1,1,1,0,1,0])
1005+
vm.n='bb'
1006+
}).then(()=>{
1007+
// B should be reused, and made latest
1008+
assertCount([1,1,1,0,1,0])
1009+
vm.n='aa'
1010+
}).then(()=>{
1011+
// C should be pruned because B was used last so C is the oldest cached
1012+
assertCount([2,1,1,0,1,1])
1013+
}).then(done)
1014+
})
9491015
}
9501016
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp