mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-21 21:25:11 +00:00
fix(nuxt): render a div when client-only hydrates w/o element (#23899)
This commit is contained in:
parent
8c77ce81b9
commit
a037512562
@ -40,7 +40,7 @@ export function createClientOnly<T extends ComponentOptions> (component: T) {
|
||||
? createElementVNode(res.type, res.props, res.children, res.patchFlag, res.dynamicProps, res.shapeFlag)
|
||||
: h(res)
|
||||
} else {
|
||||
const fragment = getFragmentHTML(ctx._.vnode.el ?? null)
|
||||
const fragment = getFragmentHTML(ctx._.vnode.el ?? null) ?? ['<div></div>']
|
||||
return process.client ? createStaticVNode(fragment.join(''), fragment.length) : h('div', ctx.$attrs ?? ctx._.attrs)
|
||||
}
|
||||
}
|
||||
@ -79,7 +79,7 @@ export function createClientOnly<T extends ComponentOptions> (component: T) {
|
||||
? createElementVNode(res.type, res.props, res.children, res.patchFlag, res.dynamicProps, res.shapeFlag)
|
||||
: h(res)
|
||||
} else {
|
||||
const fragment = getFragmentHTML(instance?.vnode.el ?? null)
|
||||
const fragment = getFragmentHTML(instance?.vnode.el ?? null) ?? ['<div></div>']
|
||||
return process.client ? createStaticVNode(fragment.join(''), fragment.length) : h('div', ctx.attrs)
|
||||
}
|
||||
}
|
||||
|
@ -73,10 +73,10 @@ export default defineComponent({
|
||||
|
||||
const ssrHTML = ref<string>('')
|
||||
if (import.meta.client) {
|
||||
const renderedHTML = getFragmentHTML(instance.vnode?.el ?? null).join('')
|
||||
const renderedHTML = getFragmentHTML(instance.vnode?.el ?? null)?.join('') ?? ''
|
||||
if (renderedHTML && nuxtApp.isHydrating) {
|
||||
setPayload(`${props.name}_${hashId.value}`, {
|
||||
html: getFragmentHTML(instance.vnode?.el ?? null, true).join(''),
|
||||
html: getFragmentHTML(instance.vnode?.el ?? null, true)?.join('') ?? '',
|
||||
state: {},
|
||||
head: {
|
||||
link: [],
|
||||
|
@ -104,7 +104,7 @@ export function vforToArray (source: any): any[] {
|
||||
* @param withoutSlots purge all slots from the HTML string retrieved
|
||||
* @returns {string[]} An array of string which represent the content of each element. Use `.join('')` to retrieve a component vnode.el HTML
|
||||
*/
|
||||
export function getFragmentHTML (element: RendererNode | null, withoutSlots = false): string[] {
|
||||
export function getFragmentHTML (element: RendererNode | null, withoutSlots = false): string[] | null {
|
||||
if (element) {
|
||||
if (element.nodeName === '#comment' && element.nodeValue === '[') {
|
||||
return getFragmentChildren(element, [], withoutSlots)
|
||||
@ -116,7 +116,7 @@ export function getFragmentHTML (element: RendererNode | null, withoutSlots = fa
|
||||
}
|
||||
return [element.outerHTML]
|
||||
}
|
||||
return []
|
||||
return null
|
||||
}
|
||||
|
||||
function getFragmentChildren (element: RendererNode | null, blocks: string[] = [], withoutSlots = false) {
|
||||
|
@ -362,6 +362,13 @@ describe('pages', () => {
|
||||
|
||||
expect(pageErrors).toEqual([])
|
||||
await page.close()
|
||||
// don't expect any errors or warning on client-side navigation
|
||||
const { page: page2, consoleLogs: consoleLogs2 } = await renderPage('/')
|
||||
await page2.locator('#to-client-only-components').click()
|
||||
// force wait for a few ticks
|
||||
await page2.waitForTimeout(50)
|
||||
expect(consoleLogs2.some(log => log.type === 'error' || log.type === 'warning')).toBeFalsy()
|
||||
await page2.close()
|
||||
})
|
||||
|
||||
it('/wrapper-expose/layout', async () => {
|
||||
|
3
test/fixtures/basic/pages/index.vue
vendored
3
test/fixtures/basic/pages/index.vue
vendored
@ -32,6 +32,9 @@
|
||||
<NuxtLink to="/chunk-error" :prefetch="false">
|
||||
Chunk error
|
||||
</NuxtLink>
|
||||
<NuxtLink id="to-client-only-components" to="/client-only-components">
|
||||
createClientOnly()
|
||||
</NuxtLink>
|
||||
<NuxtLink id="middleware-abort-non-fatal" to="/middleware-abort-non-fatal" :prefetch="false">
|
||||
Middleware abort navigation
|
||||
</NuxtLink>
|
||||
|
Loading…
Reference in New Issue
Block a user