Skip to content

Commit 1237387

Browse files
committed
fix(keep-alive): should update re-activated component with latest props
1 parent bfae9b2 commit 1237387

File tree

3 files changed

+55
-12
lines changed

3 files changed

+55
-12
lines changed

packages/runtime-core/__tests__/components/KeepAlive.spec.ts

+27
Original file line numberDiff line numberDiff line change
@@ -531,5 +531,32 @@ describe('KeepAlive', () => {
531531
await nextTick()
532532
expect(Foo.unmounted).not.toHaveBeenCalled()
533533
})
534+
535+
test('should update re-activated component if props have changed', async () => {
536+
const Foo = (props: { n: number }) => props.n
537+
538+
const toggle = ref(true)
539+
const n = ref(0)
540+
541+
const App = {
542+
setup() {
543+
return () =>
544+
h(KeepAlive, () => (toggle.value ? h(Foo, { n: n.value }) : null))
545+
}
546+
}
547+
548+
render(h(App), root)
549+
expect(serializeInner(root)).toBe(`0`)
550+
551+
toggle.value = false
552+
await nextTick()
553+
expect(serializeInner(root)).toBe(`<!---->`)
554+
555+
n.value++
556+
await nextTick()
557+
toggle.value = true
558+
await nextTick()
559+
expect(serializeInner(root)).toBe(`1`)
560+
})
534561
})
535562
})

packages/runtime-core/src/components/KeepAlive.ts

+25-11
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ export interface KeepAliveSink {
4141
activate: (
4242
vnode: VNode,
4343
container: RendererElement,
44-
anchor: RendererNode | null
44+
anchor: RendererNode | null,
45+
isSVG: boolean,
46+
optimized: boolean
4547
) => void
4648
deactivate: (vnode: VNode) => void
4749
}
@@ -78,6 +80,7 @@ const KeepAliveImpl = {
7880
const sink = instance.sink as KeepAliveSink
7981
const {
8082
renderer: {
83+
p: patch,
8184
m: move,
8285
um: _unmount,
8386
o: { createElement }
@@ -86,13 +89,24 @@ const KeepAliveImpl = {
8689
} = sink
8790
const storageContainer = createElement('div')
8891

89-
sink.activate = (vnode, container, anchor) => {
92+
sink.activate = (vnode, container, anchor, isSVG, optimized) => {
93+
const child = vnode.component!
9094
move(vnode, container, anchor, MoveType.ENTER, parentSuspense)
95+
// in case props have changed
96+
patch(
97+
child.vnode,
98+
vnode,
99+
container,
100+
anchor,
101+
instance,
102+
parentSuspense,
103+
isSVG,
104+
optimized
105+
)
91106
queuePostRenderEffect(() => {
92-
const component = vnode.component!
93-
component.isDeactivated = false
94-
if (component.a) {
95-
invokeHooks(component.a)
107+
child.isDeactivated = false
108+
if (child.a) {
109+
invokeHooks(child.a)
96110
}
97111
}, parentSuspense)
98112
}
@@ -181,19 +195,19 @@ const KeepAliveImpl = {
181195
}
182196

183197
const key = vnode.key == null ? comp : vnode.key
184-
const cached = cache.get(key)
198+
const cachedVNode = cache.get(key)
185199

186200
// clone vnode if it's reused because we are going to mutate it
187201
if (vnode.el) {
188202
vnode = cloneVNode(vnode)
189203
}
190204
cache.set(key, vnode)
191205

192-
if (cached) {
206+
if (cachedVNode) {
193207
// copy over mounted state
194-
vnode.el = cached.el
195-
vnode.anchor = cached.anchor
196-
vnode.component = cached.component
208+
vnode.el = cachedVNode.el
209+
vnode.anchor = cachedVNode.anchor
210+
vnode.component = cachedVNode.component
197211
if (vnode.transition) {
198212
// recursively update transition hooks on subTree
199213
setTransitionHooks(vnode, vnode.transition!)

packages/runtime-core/src/renderer.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,9 @@ function baseCreateRenderer(
946946
;(parentComponent!.sink as KeepAliveSink).activate(
947947
n2,
948948
container,
949-
anchor
949+
anchor,
950+
isSVG,
951+
optimized
950952
)
951953
} else {
952954
mountComponent(

0 commit comments

Comments
 (0)