fix(nuxt): provide route component names to KeepAlive cache (#24024)

This commit is contained in:
Aaron_Zhou 2023-11-15 00:56:31 +08:00 committed by GitHub
parent b90b631df0
commit 5493d60c4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 177 additions and 10 deletions

View File

@ -4,7 +4,6 @@ import type { RouteLocation, RouteLocationNormalizedLoaded } from '#vue-router'
import { PageRouteSymbol } from './injections'
export const RouteProvider = defineComponent({
name: 'RouteProvider',
props: {
vnode: {
type: Object as () => VNode,

View File

@ -88,13 +88,15 @@ export default defineComponent({
{ onAfterLeave: () => { nuxtApp.callHook('page:transition:finish', routeProps.Component) } }
].filter(Boolean))
const keepaliveConfig = props.keepalive ?? routeProps.route.meta.keepalive ?? (defaultKeepaliveConfig as KeepAliveProps)
vnode = _wrapIf(Transition, hasTransition && transitionProps,
wrapInKeepAlive(props.keepalive ?? routeProps.route.meta.keepalive ?? (defaultKeepaliveConfig as KeepAliveProps), h(Suspense, {
wrapInKeepAlive(keepaliveConfig, h(Suspense, {
suspensible: true,
onPending: () => nuxtApp.callHook('page:start', routeProps.Component),
onResolve: () => { nextTick(() => nuxtApp.callHook('page:finish', routeProps.Component).finally(done)) }
}, {
default: () => h(RouteProvider, {
default: () => {
const providerVNode = h(RouteProvider, {
key: key || undefined,
vnode: routeProps.Component,
route: routeProps.route,
@ -102,6 +104,11 @@ export default defineComponent({
trackRootNodes: hasTransition,
vnodeRef: pageRef
})
if (import.meta.client && keepaliveConfig) {
(providerVNode.type as any).name = (routeProps.Component.type as any).name || (routeProps.Component.type as any).__name || 'RouteProvider'
}
return providerVNode
}
})
)).default()

View File

@ -2017,6 +2017,87 @@ describe.runIf(isDev())('component testing', () => {
})
})
describe('keepalive', () => {
it('should not keepalive by default', async () => {
const { page, consoleLogs } = await renderPage('/keepalive')
const pageName = 'not-keepalive'
await page.click(`#${pageName}`)
await page.waitForTimeout(25)
expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([`${pageName}: onMounted`])
await page.close()
})
it('should not keepalive when included in app config but config in nuxt-page is not undefined', async () => {
const { page, consoleLogs } = await renderPage('/keepalive')
const pageName = 'keepalive-in-config'
await page.click(`#${pageName}`)
await page.waitForTimeout(25)
expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([`${pageName}: onMounted`])
await page.close()
})
it('should not keepalive when included in app config but exclueded in nuxt-page', async () => {
const { page, consoleLogs } = await renderPage('/keepalive')
const pageName = 'not-keepalive-in-nuxtpage'
await page.click(`#${pageName}`)
await page.waitForTimeout(25)
expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([`${pageName}: onMounted`])
await page.close()
})
it('should keepalive when included in nuxt-page', async () => {
const { page, consoleLogs } = await renderPage('/keepalive')
const pageName = 'keepalive-in-nuxtpage'
await page.click(`#${pageName}`)
await page.waitForTimeout(25)
expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([`${pageName}: onMounted`, `${pageName}: onActivated`])
await page.close()
})
it('should preserve keepalive config when navigate routes in nuxt-page', async () => {
const { page, consoleLogs } = await renderPage('/keepalive')
await page.click('#keepalive-in-nuxtpage')
await page.waitForTimeout(25)
await page.click('#keepalive-in-nuxtpage-2')
await page.waitForTimeout(25)
await page.click('#keepalive-in-nuxtpage')
await page.waitForTimeout(25)
await page.click('#not-keepalive')
await page.waitForTimeout(25)
await page.click('#keepalive-in-nuxtpage-2')
await page.waitForTimeout(25)
expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([
'keepalive-in-nuxtpage: onMounted',
'keepalive-in-nuxtpage: onActivated',
'keepalive-in-nuxtpage: onDeactivated',
'keepalive-in-nuxtpage-2: onMounted',
'keepalive-in-nuxtpage-2: onActivated',
'keepalive-in-nuxtpage: onActivated',
'keepalive-in-nuxtpage-2: onDeactivated',
'keepalive-in-nuxtpage: onDeactivated',
'not-keepalive: onMounted',
'keepalive-in-nuxtpage-2: onActivated',
'not-keepalive: onUnmounted'
])
await page.close()
})
})
function normaliseIslandResult (result: NuxtIslandResponse) {
return {
...result,

View File

@ -0,0 +1,6 @@
export function useLifecyleLogs (name: string) {
onMounted(() => console.log(`${name}: onMounted`))
onUnmounted(() => console.log(`${name}: onUnmounted`))
onActivated(() => console.log(`${name}: onActivated`))
onDeactivated(() => console.log(`${name}: onDeactivated`))
}

View File

@ -22,6 +22,9 @@ export default defineNuxtConfig({
{ charset: 'utf-8' },
{ name: 'description', content: 'Nuxt Fixture' }
]
},
keepalive: {
include: ['keepalive-in-config', 'not-keepalive-in-nuxtpage']
}
},
buildDir: process.env.NITRO_BUILD_DIR,

26
test/fixtures/basic/pages/keepalive.vue vendored Normal file
View File

@ -0,0 +1,26 @@
<script setup lang="ts">
const links = ['keepalive-in-config', 'not-keepalive', 'keepalive-in-nuxtpage', 'keepalive-in-nuxtpage-2', 'not-keepalive-in-nuxtpage']
</script>
<template>
<div>
<h1>Keepalive Test</h1>
<NuxtLink
id="keepalive-home"
to="/keepalive"
>
Keepalive Home
</NuxtLink>
<div :style="{ display: 'flex', flexDirection: 'column', marginTop: '10px' }">
<NuxtLink
v-for="link in links"
:id="link"
:key="link"
:to="`/keepalive/${link}`"
>
{{ link }}
</NuxtLink>
</div>
<NuxtPage :keepalive="{ include: ['keepalive-in-nuxtpage', 'keepalive-in-nuxtpage-2'], exclude: ['not-keepalive-in-nuxtpage'] }" />
</div>
</template>

View File

@ -0,0 +1,9 @@
<script setup lang="ts">
useLifecyleLogs('keepalive-in-config')
</script>
<template>
<div>
<h2>Keepalive in Config</h2>
</div>
</template>

View File

@ -0,0 +1,9 @@
<script setup lang="ts">
useLifecyleLogs('keepalive-in-nuxtpage-2')
</script>
<template>
<div>
<h2>Keepalive in `nuxt-page` 2</h2>
</div>
</template>

View File

@ -0,0 +1,9 @@
<script setup lang="ts">
useLifecyleLogs('keepalive-in-nuxtpage')
</script>
<template>
<div>
<h2>Keepalive in `nuxt-page`</h2>
</div>
</template>

View File

@ -0,0 +1,9 @@
<script setup lang="ts">
useLifecyleLogs('not-keepalive-in-nuxtpage')
</script>
<template>
<div>
<h2>Not Keepalive in `nuxt-page`</h2>
</div>
</template>

View File

@ -0,0 +1,9 @@
<script setup lang="ts">
useLifecyleLogs('not-keepalive')
</script>
<template>
<div>
<h2>Not Keepalive</h2>
</div>
</template>