mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
fix(nuxt): enable suspensible behaviour for nested pages (#20777)
This commit is contained in:
parent
d1577889ad
commit
5e74fe4e0b
@ -54,6 +54,7 @@ export default defineComponent({
|
||||
|
||||
return _wrapIf(Transition, hasTransition && transitionProps,
|
||||
wrapInKeepAlive(props.keepalive ?? routeProps.route.meta.keepalive ?? (defaultKeepaliveConfig as KeepAliveProps), h(Suspense, {
|
||||
suspensible: true,
|
||||
onPending: () => nuxtApp.callHook('page:start', routeProps.Component),
|
||||
onResolve: () => { nextTick(() => nuxtApp.callHook('page:finish', routeProps.Component).finally(done)) }
|
||||
}, { default: () => h(RouteProvider, { key, routeProps, pageKey: key, hasTransition } as {}) })
|
||||
|
@ -891,6 +891,36 @@ describe('deferred app suspense resolve', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('nested suspense', () => {
|
||||
const navigations = [
|
||||
['/suspense/sync-1/async-1/', '/suspense/sync-2/async-1/'],
|
||||
['/suspense/sync-1/sync-1/', '/suspense/sync-2/async-1/'],
|
||||
['/suspense/async-1/async-1/', '/suspense/async-2/async-1/'],
|
||||
['/suspense/async-1/sync-1/', '/suspense/async-2/async-1/']
|
||||
]
|
||||
|
||||
it.each(navigations)('should navigate from %s to %s with no white flash', async (start, nav) => {
|
||||
const page = await createPage(start, {})
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
const slug = nav.replace(/[/-]+/g, '-')
|
||||
await page.click(`[href^="${nav}"]`)
|
||||
|
||||
const text = await page.waitForFunction(slug => document.querySelector(`#${slug}`)?.innerHTML, slug)
|
||||
// @ts-expect-error TODO: fix upstream in playwright - types for evaluate are broken
|
||||
.then(r => r.evaluate(r => r))
|
||||
|
||||
// expect(text).toMatchInlineSnapshot()
|
||||
|
||||
// const parent = await page.waitForSelector(`#${slug}`, { state: 'attached' })
|
||||
|
||||
// const text = await parent.innerText()
|
||||
expect(text).toContain('Async child: 2 - 1')
|
||||
|
||||
await page.close()
|
||||
})
|
||||
})
|
||||
|
||||
// Bug #6592
|
||||
describe('page key', () => {
|
||||
it('should not cause run of setup if navigation not change page key and layout', async () => {
|
||||
|
22
test/fixtures/basic/pages/suspense.vue
vendored
Normal file
22
test/fixtures/basic/pages/suspense.vue
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<script setup>
|
||||
definePageMeta({
|
||||
// Nested <Suspense> + <Transition> is still buggy
|
||||
pageTransition: false,
|
||||
layoutTransition: false
|
||||
})
|
||||
const links = ['sync', 'async'].flatMap(parent => [1, 2].flatMap(p => ['sync', 'async'].flatMap(child => [1, 2].map(c => `/suspense/${parent}-${p}/${child}-${c}/`))))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
This exists to test synchronous transitions between nested Suspense components.
|
||||
<hr>
|
||||
<NuxtLink v-for="link in links" :key="link" :to="link" style="display: block;">
|
||||
{{ link }}
|
||||
</NuxtLink>
|
||||
<hr>
|
||||
<div>
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
14
test/fixtures/basic/pages/suspense/async-[parent].vue
vendored
Normal file
14
test/fixtures/basic/pages/suspense/async-[parent].vue
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
console.log('[async]')
|
||||
const route = useRoute('suspense-async-parent')
|
||||
await new Promise(resolve => setTimeout(resolve, 100))
|
||||
console.log('[async] running async data')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :id="route.path.replace(/[/-]+/g, '-')">
|
||||
Async parent: {{ route.params.parent }}
|
||||
<hr>
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</template>
|
15
test/fixtures/basic/pages/suspense/async-[parent]/async-[child].vue
vendored
Normal file
15
test/fixtures/basic/pages/suspense/async-[parent]/async-[child].vue
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
console.log('[async] [async]')
|
||||
const route = useRoute('suspense-async-parent-async-child')
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
console.log(`[async] [${route.params.parent}] [async] [${route.params.child}] running async data`)
|
||||
const data = route.params
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
Async child: {{ route.params.parent }} - {{ route.params.child }}
|
||||
<hr>
|
||||
{{ data }}
|
||||
</div>
|
||||
</template>
|
10
test/fixtures/basic/pages/suspense/async-[parent]/sync-[child].vue
vendored
Normal file
10
test/fixtures/basic/pages/suspense/async-[parent]/sync-[child].vue
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
console.log('[async] [sync]')
|
||||
const route = useRoute('suspense-async-parent-sync-child')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
Sync child: {{ route.params.parent }} - {{ route.params.child }}
|
||||
</div>
|
||||
</template>
|
12
test/fixtures/basic/pages/suspense/sync-[parent].vue
vendored
Normal file
12
test/fixtures/basic/pages/suspense/sync-[parent].vue
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
console.log('[sync]')
|
||||
const route = useRoute('suspense-async-parent')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :id="route.path.replace(/[/-]+/g, '-')">
|
||||
Sync parent: {{ route.params.parent }}
|
||||
<hr>
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</template>
|
15
test/fixtures/basic/pages/suspense/sync-[parent]/async-[child].vue
vendored
Normal file
15
test/fixtures/basic/pages/suspense/sync-[parent]/async-[child].vue
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
console.log('[sync] [async]')
|
||||
const route = useRoute('suspense-async-parent-sync-child')
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
console.log(`[async] [${route.params.parent}] [async] [${route.params.child}] running async data`)
|
||||
const data = route.params
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
Async child: {{ route.params.parent }} - {{ route.params.child }}
|
||||
<hr>
|
||||
{{ data }}
|
||||
</div>
|
||||
</template>
|
10
test/fixtures/basic/pages/suspense/sync-[parent]/sync-[child].vue
vendored
Normal file
10
test/fixtures/basic/pages/suspense/sync-[parent]/sync-[child].vue
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
console.log('[sync] [sync]')
|
||||
const route = useRoute('suspense-sync-parent-sync-child')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
Sync child: {{ route.params.parent }} - {{ route.params.child }}
|
||||
</div>
|
||||
</template>
|
Loading…
Reference in New Issue
Block a user