}
})
+ describe('dynamic anchor', () => {
+ test('two consecutive components', () => {
+ const Comp = {
+ render() {
+ return createTextVNode('foo')
+ },
+ }
+ const { vnode, container } = mountWithHydration(
+ `<div><span></span>foo<!--[[-->foo<!--]]--><span></span></div>`,
+ () => h('div', null, [h('span'), h(Comp), h(Comp), h('span')]),
+ )
+ expect(vnode.el).toBe(container.firstChild)
+ expect(`Hydration children mismatch`).not.toHaveBeenWarned()
+ })
+
+ test('multiple consecutive components', () => {
+ const Comp = {
+ render() {
+ return createTextVNode('foo')
+ },
+ }
+ const { vnode, container } = mountWithHydration(
+ `<div><span></span>foo<!--[[-->foo<!--]]-->foo<span></span></div>`,
+ () => h('div', null, [h('span'), h(Comp), h(Comp), h(Comp), h('span')]),
+ )
+ expect(vnode.el).toBe(container.firstChild)
+ expect(`Hydration children mismatch`).not.toHaveBeenWarned()
+ })
+ })
+
+ test('hmr reload child wrapped in KeepAlive', async () => {
+ const id = 'child-reload'
+ const Child = {
+ __hmrId: id,
+ template: `<div>foo</div>`,
+ }
+ createRecord(id, Child)
+
+ const appId = 'test-app-id'
+ const App = {
+ __hmrId: appId,
+ components: { Child },
+ template: `
+ <div>
+ <KeepAlive>
+ <Child />
+ </KeepAlive>
+ </div>
+ `,
+ }
+
+ const root = document.createElement('div')
+ root.innerHTML = await renderToString(h(App))
+ createSSRApp(App).mount(root)
+ expect(root.innerHTML).toBe('<div><div>foo</div></div>')
+
+ reload(id, {
+ __hmrId: id,
+ template: `<div>bar</div>`,
+ })
+ await nextTick()
+ expect(root.innerHTML).toBe('<div><div>bar</div></div>')
+ })
+
+ test('hmr root reload', async () => {
+ const appId = 'test-app-id'
+ const App = {
+ __hmrId: appId,
+ template: `<div>foo</div>`,
+ }
+
+ const root = document.createElement('div')
+ root.innerHTML = await renderToString(h(App))
+ createSSRApp(App).mount(root)
+ expect(root.innerHTML).toBe('<div>foo</div>')
+
+ reload(appId, {
+ __hmrId: appId,
+ template: `<div>bar</div>`,
+ })
+ await nextTick()
+ expect(root.innerHTML).toBe('<div>bar</div>')
+ })
+
describe('mismatch handling', () => {
test('text node', () => {
const { container } = mountWithHydration(`foo`, () => 'bar')
movedChildren.forEach(c => {
const el = c.el as ElementWithTransition
- const style = el.style
- addTransitionClass(el, moveClass)
- style.transform = style.webkitTransform = style.transitionDuration = ''
- const cb = ((el as any)[moveCbKey] = (e: TransitionEvent) => {
- if (e && e.target !== el) {
- return
- }
- if (!e || /transform$/.test(e.propertyName)) {
- el.removeEventListener('transitionend', cb)
- ;(el as any)[moveCbKey] = null
- removeTransitionClass(el, moveClass)
- }
- })
- el.addEventListener('transitionend', cb)
+ handleMovedChildren(el, moveClass)
})
+ prevChildren = []
})
return () => {
rawProps?: LooseRawProps | null,
rawSlots?: LooseRawSlots | null,
isSingleRoot?: boolean,
+ appContext?: GenericAppContext,
): HTMLElement | VaporComponentInstance {
if (!isString(comp)) {
- return createComponent(comp, rawProps, rawSlots, isSingleRoot)
+ return createComponent(comp, rawProps, rawSlots, isSingleRoot, appContext)
}
- const el = document.createElement(comp)
+ const _insertionParent = insertionParent
+ const _insertionAnchor = insertionAnchor
+ if (isHydrating) {
+ locateHydrationNode()
+ } else {
+ resetInsertionState()
+ }
+
+ const el = createElement(comp)
// mark single root
;(el as any).$root = isSingleRoot
).toBe(`<div><p>1</p><p>2</p></div>`)
})
- ).toBe(`<div><!--[--> new header <!--]--></div>`)
+ // #12438
+ test('async component slot with v-if true', async () => {
+ const Layout = defineAsyncComponent(() =>
+ Promise.resolve({
+ template: `<div><slot name="header">default header</slot></div>`,
+ }),
+ )
+ const LayoutLoader = {
+ setup(_: any, context: any) {
+ return () => h(Layout, {}, context.slots)
+ },
+ }
+ expect(
+ await renderToString(
+ createApp({
+ components: {
+ LayoutLoader,
+ },
+ template: `
+ <Suspense>
+ <LayoutLoader>
+ <template v-if="true" #header>
+ new header
+ </template>
+ </LayoutLoader>
+ </Suspense>
+ `,
+ }),
+ ),
++ ).toBe(`<div><!--[--> new header <!--]--><!--slot--></div>`)
+ })
+
// #11326
test('dynamic component slot', async () => {
expect(