Skip to content

Commit a54bff2

Browse files
authoredNov 10, 2022
fix(hmr/keep-alive): fix error in reload component (#7049)
fix #7042
1 parent 0594400 commit a54bff2

File tree

3 files changed

+76
-3
lines changed

3 files changed

+76
-3
lines changed
 

‎packages/runtime-core/__tests__/hmr.spec.ts

+67
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,73 @@ describe('hot module replacement', () => {
151151
expect(mountSpy).toHaveBeenCalledTimes(1)
152152
})
153153

154+
// #7042
155+
test('reload KeepAlive slot', async () => {
156+
const root = nodeOps.createElement('div')
157+
const childId = 'test-child-keep-alive'
158+
const unmountSpy = jest.fn()
159+
const mountSpy = jest.fn()
160+
const activeSpy = jest.fn()
161+
const deactiveSpy = jest.fn()
162+
163+
const Child: ComponentOptions = {
164+
__hmrId: childId,
165+
data() {
166+
return { count: 0 }
167+
},
168+
unmounted: unmountSpy,
169+
render: compileToFunction(`<div>{{ count }}</div>`)
170+
}
171+
createRecord(childId, Child)
172+
173+
const Parent: ComponentOptions = {
174+
components: { Child },
175+
data() {
176+
return { toggle: true }
177+
},
178+
render: compileToFunction(
179+
`<button @click="toggle = !toggle"></button><KeepAlive><Child v-if="toggle" /></KeepAlive>`
180+
)
181+
}
182+
183+
render(h(Parent), root)
184+
expect(serializeInner(root)).toBe(`<button></button><div>0</div>`)
185+
186+
reload(childId, {
187+
__hmrId: childId,
188+
data() {
189+
return { count: 1 }
190+
},
191+
mounted: mountSpy,
192+
unmounted: unmountSpy,
193+
activated: activeSpy,
194+
deactivated: deactiveSpy,
195+
render: compileToFunction(`<div>{{ count }}</div>`)
196+
})
197+
await nextTick()
198+
expect(serializeInner(root)).toBe(`<button></button><div>1</div>`)
199+
expect(unmountSpy).toHaveBeenCalledTimes(1)
200+
expect(mountSpy).toHaveBeenCalledTimes(1)
201+
expect(activeSpy).toHaveBeenCalledTimes(1)
202+
expect(deactiveSpy).toHaveBeenCalledTimes(0)
203+
204+
// should not unmount when toggling
205+
triggerEvent(root.children[1] as TestElement, 'click')
206+
await nextTick()
207+
expect(unmountSpy).toHaveBeenCalledTimes(1)
208+
expect(mountSpy).toHaveBeenCalledTimes(1)
209+
expect(activeSpy).toHaveBeenCalledTimes(1)
210+
expect(deactiveSpy).toHaveBeenCalledTimes(1)
211+
212+
// should not mount when toggling
213+
triggerEvent(root.children[1] as TestElement, 'click')
214+
await nextTick()
215+
expect(unmountSpy).toHaveBeenCalledTimes(1)
216+
expect(mountSpy).toHaveBeenCalledTimes(1)
217+
expect(activeSpy).toHaveBeenCalledTimes(2)
218+
expect(deactiveSpy).toHaveBeenCalledTimes(1)
219+
})
220+
154221
test('reload class component', async () => {
155222
const root = nodeOps.createElement('div')
156223
const childId = 'test4-child'

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
invokeArrayFns
3232
} from '@vue/shared'
3333
import { watch } from '../apiWatch'
34-
import { hmrDirtyComponents } from '../hmr'
3534
import {
3635
RendererInternals,
3736
queuePostRenderEffect,
@@ -281,8 +280,7 @@ const KeepAliveImpl: ComponentOptions = {
281280

282281
if (
283282
(include && (!name || !matches(include, name))) ||
284-
(exclude && name && matches(exclude, name)) ||
285-
(__DEV__ && hmrDirtyComponents.has(comp))
283+
(exclude && name && matches(exclude, name))
286284
) {
287285
current = vnode
288286
return rawVNode

‎packages/runtime-core/src/vnode.ts

+8
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,14 @@ export function isSameVNodeType(n1: VNode, n2: VNode): boolean {
357357
n2.shapeFlag & ShapeFlags.COMPONENT &&
358358
hmrDirtyComponents.has(n2.type as ConcreteComponent)
359359
) {
360+
// #7042, ensure the vnode being unmounted during HMR
361+
if (n1.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
362+
n1.shapeFlag -= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
363+
}
364+
// #7042, ensure the vnode being mounted as fresh during HMR
365+
if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
366+
n2.shapeFlag -= ShapeFlags.COMPONENT_KEPT_ALIVE
367+
}
360368
// HMR only: if the component has been hot-updated, force a reload.
361369
return false
362370
}

0 commit comments

Comments
 (0)
Please sign in to comment.