diff --git a/packages/runtime-core/__tests__/components/Teleport.spec.ts b/packages/runtime-core/__tests__/components/Teleport.spec.ts index 79125cd04df..1229c5325b7 100644 --- a/packages/runtime-core/__tests__/components/Teleport.spec.ts +++ b/packages/runtime-core/__tests__/components/Teleport.spec.ts @@ -10,6 +10,7 @@ import { markRaw, nextTick, nodeOps, + onMounted, h as originalH, ref, render, @@ -18,6 +19,10 @@ import { } from '@vue/runtime-test' import { Fragment, createCommentVNode, createVNode } from '../../src/vnode' import { compile, createApp as createDOMApp, render as domRender } from 'vue' +import type { HMRRuntime } from '../../src/hmr' + +declare var __VUE_HMR_RUNTIME__: HMRRuntime +const { rerender, createRecord } = __VUE_HMR_RUNTIME__ describe('renderer: teleport', () => { describe('eager mode', () => { @@ -741,4 +746,56 @@ describe('renderer: teleport', () => { expect(tRefInMounted).toBe(target.children[1]) }) } + + test('handle update and hmr rerender', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + + const Comp = { + setup() { + const cls = ref('foo') + onMounted(() => { + // trigger update + cls.value = 'bar' + }) + return { cls, target } + }, + template: ` + +
+
+ +
+
+
+ `, + } + + const appId = 'test-app-id' + const App = { + __hmrId: appId, + components: { Comp }, + render() { + return originalH(Comp, null, { default: () => originalH('div', 'foo') }) + }, + } + createRecord(appId, App) + + domRender(originalH(App), root) + expect(target.innerHTML).toBe( + '
foo
', + ) + await nextTick() + expect(target.innerHTML).toBe( + '
foo
', + ) + + rerender(appId, () => + originalH(Comp, null, { default: () => originalH('div', 'bar') }), + ) + await nextTick() + expect(target.innerHTML).toBe( + '
bar
', + ) + }) }) diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts index fe6fa36c1ca..fc2ee4c086f 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/packages/runtime-core/src/components/Teleport.ts @@ -220,7 +220,8 @@ export const TeleportImpl = { // even in block tree mode we need to make sure all root-level nodes // in the teleport inherit previous DOM references so that they can // be moved in future patches. - traverseStaticChildren(n1, n2, true) + // in dev mode, deep traversal is necessary for HMR + traverseStaticChildren(n1, n2, !__DEV__) } else if (!optimized) { patchChildren( n1,