Skip to content

Commit cdc0bc9

Browse files
committed
improve keep-alive: use component-based API
1 parent 7c3db41 commit cdc0bc9

File tree

7 files changed

+51
-48
lines changed

7 files changed

+51
-48
lines changed

flow/compiler.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ declare type ASTElement = {
8282
ns?: string;
8383

8484
component?: string;
85-
keepAlive?: boolean;
8685
inlineTemplate?: true;
8786
transitionMode?: string | null;
8887
slotName?: ?string;

src/compiler/codegen/index.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,6 @@ function genElement (el: ASTElement): string {
6767
for (let i = 0; i < transforms.length; i++) {
6868
code = transforms[i](el, code)
6969
}
70-
// check keep-alive
71-
if (el.keepAlive) {
72-
code = `_h("KeepAlive",{props:{child:${code}}})`
73-
}
7470
return code
7571
}
7672
}

src/compiler/parser/index.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,6 @@ function processComponent (el) {
345345
if ((binding = getBindingAttr(el, 'is'))) {
346346
el.component = binding
347347
}
348-
if (getAndRemoveAttr(el, 'keep-alive') != null) {
349-
el.keepAlive = true
350-
}
351348
if (getAndRemoveAttr(el, 'inline-template') != null) {
352349
el.inlineTemplate = true
353350
}

src/core/components/keep-alive.js

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,30 @@
11
import { callHook } from 'core/instance/lifecycle'
2-
import { getRealChild } from 'core/vdom/helpers'
2+
import { getFirstComponentChild } from 'core/vdom/helpers'
33

44
export default {
55
name: 'keep-alive',
66
abstract: true,
7-
props: {
8-
child: Object
9-
},
107
created () {
118
this.cache = Object.create(null)
129
},
1310
render () {
14-
const rawChild = this.child
15-
const realChild = getRealChild(this.child)
16-
if (realChild && realChild.componentOptions) {
17-
const opts = realChild.componentOptions
18-
// same constructor may get registered as different local components
19-
// so cid alone is not enough (#3269)
20-
const key = opts.Ctor.cid + '::' + opts.tag
11+
const vnode = getFirstComponentChild(this.$slots.default)
12+
if (vnode && vnode.componentOptions) {
13+
const opts = vnode.componentOptions
14+
const key = vnode.key == null
15+
// same constructor may get registered as different local components
16+
// so cid alone is not enough (#3269)
17+
? opts.Ctor.cid + '::' + opts.tag
18+
: vnode.key
2119
if (this.cache[key]) {
22-
const child = realChild.child = this.cache[key].child
23-
realChild.elm = this.$el = child.$el
20+
const child = vnode.child = this.cache[key].child
21+
vnode.elm = this.$el = child.$el
2422
} else {
25-
this.cache[key] = realChild
23+
this.cache[key] = vnode
2624
}
27-
realChild.data.keepAlive = true
25+
vnode.data.keepAlive = true
2826
}
29-
return rawChild
27+
return vnode
3028
},
3129
destroyed () {
3230
for (const key in this.cache) {

src/core/vdom/helpers.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,8 @@ function applyNS (vnode, ns) {
5656
}
5757
}
5858

59-
// in case the child is also an abstract component, e.g. <transition-control>
60-
// we want to recrusively retrieve the real component to be rendered
61-
export function getRealChild (vnode: ?VNode): ?VNode {
62-
const compOptions = vnode && vnode.componentOptions
63-
if (compOptions && compOptions.Ctor.options.abstract) {
64-
return getRealChild(compOptions.propsData && compOptions.propsData.child)
65-
} else {
66-
return vnode
67-
}
59+
export function getFirstComponentChild (children: ?Array<any>) {
60+
return children && children.filter(c => c && c.componentOptions)[0]
6861
}
6962

7063
export function mergeVNodeHook (def: Object, key: string, hook: Function) {

src/platforms/web/runtime/components/transition.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { warn } from 'core/util/index'
77
import { camelize, extend } from 'shared/util'
8-
import { getRealChild, mergeVNodeHook } from 'core/vdom/helpers'
8+
import { mergeVNodeHook, getFirstComponentChild } from 'core/vdom/helpers'
99

1010
export const transitionProps = {
1111
name: String,
@@ -21,6 +21,17 @@ export const transitionProps = {
2121
appearActiveClass: String
2222
}
2323

24+
// in case the child is also an abstract component, e.g. <keep-alive>
25+
// we want to recrusively retrieve the real component to be rendered
26+
function getRealChild (vnode: ?VNode): ?VNode {
27+
const compOptions = vnode && vnode.componentOptions
28+
if (compOptions && compOptions.Ctor.options.abstract) {
29+
return getRealChild(getFirstComponentChild(compOptions.children))
30+
} else {
31+
return vnode
32+
}
33+
}
34+
2435
export function extractTransitionData (comp: Component): Object {
2536
const data = {}
2637
const options = comp.$options
@@ -86,8 +97,13 @@ export default {
8697
// use getRealChild() to ignore abstract components e.g. keep-alive
8798
const child = getRealChild(rawChild)
8899
/* istanbul ignore if */
89-
if (!child) return
90-
child.key = child.key || `__v${child.tag + this._uid}__`
100+
if (!child) {
101+
return rawChild
102+
}
103+
104+
child.key = child.key == null
105+
? `__v${child.tag + this._uid}__`
106+
: child.key
91107
const data = (child.data || (child.data = {})).transition = extractTransitionData(this)
92108
const oldRawChild = this._vnode
93109
const oldChild: any = getRealChild(oldRawChild)

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

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@ describe('Component keep-alive', () => {
4343

4444
it('should work', done => {
4545
const vm = new Vue({
46-
template: '<div v-if="ok"><component :is="view" keep-alive></component></div>',
46+
template: `
47+
<div v-if="ok">
48+
<keep-alive>
49+
<component :is="view"></component>
50+
</keep-alive>
51+
</div>
52+
`,
4753
data: {
4854
view: 'one',
4955
ok: true
@@ -82,11 +88,9 @@ describe('Component keep-alive', () => {
8288
const vm = new Vue({
8389
template: `<div>
8490
<transition name="test" mode="out-in" @after-leave="afterLeave">
85-
<component
86-
:is="view"
87-
class="test"
88-
keep-alive>
89-
</component>
91+
<keep-alive>
92+
<component :is="view" class="test"></component>
93+
</keep-alive>
9094
<transition>
9195
</div>`,
9296
data: {
@@ -169,11 +173,9 @@ describe('Component keep-alive', () => {
169173
const vm = new Vue({
170174
template: `<div>
171175
<transition name="test" mode="in-out" @after-enter="afterEnter">
172-
<component
173-
:is="view"
174-
class="test"
175-
keep-alive>
176-
</component>
176+
<keep-alive>
177+
<component :is="view" class="test"></component>
178+
</keep-alive>
177179
</transition>
178180
</div>`,
179181
data: {
@@ -266,7 +268,9 @@ describe('Component keep-alive', () => {
266268
const vm = new Vue({
267269
template: `<div>
268270
<transition name="test" mode="in-out" @after-enter="afterEnter">
269-
<component :is="view" class="test" keep-alive></component>
271+
<keep-alive>
272+
<component :is="view" class="test"></component>
273+
</keep-alive>
270274
</transition>
271275
</div>`,
272276
data: { view: 'one' },

0 commit comments

Comments
 (0)