markRaw,
nextTick,
nodeOps,
+ onMounted,
h as originalH,
ref,
render,
} 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', () => {
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>',
+ )
+ })
})
// 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,