fix(hmr/teleport): adjust static children traversal for HMR in dev mode (#12819)

close #12816
This commit is contained in:
edison 2025-05-02 17:18:01 +08:00 committed by GitHub
parent 0b23fd2383
commit 5e37dd0095
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 59 additions and 1 deletions

View File

@ -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: `
<Teleport :to="target">
<div :class="cls">
<div>
<slot></slot>
</div>
</div>
</Teleport>
`,
}
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(
'<div class="foo"><div><div>foo</div></div></div>',
)
await nextTick()
expect(target.innerHTML).toBe(
'<div class="bar"><div><div>foo</div></div></div>',
)
rerender(appId, () =>
originalH(Comp, null, { default: () => originalH('div', 'bar') }),
)
await nextTick()
expect(target.innerHTML).toBe(
'<div class="bar"><div><div>bar</div></div></div>',
)
})
})

View File

@ -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,