mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-23 00:50:05 +00:00
fix(nuxt): ensure provide
/ inject
work in setup
of defineNuxtComponent
(#30982)
This commit is contained in:
parent
6d9ddff209
commit
b65dfbc98e
@ -2,7 +2,7 @@ import { getCurrentInstance, reactive, toRefs } from 'vue'
|
|||||||
import type { DefineComponent, defineComponent } from 'vue'
|
import type { DefineComponent, defineComponent } from 'vue'
|
||||||
import { useHead } from '@unhead/vue'
|
import { useHead } from '@unhead/vue'
|
||||||
import type { NuxtApp } from '../nuxt'
|
import type { NuxtApp } from '../nuxt'
|
||||||
import { useNuxtApp } from '../nuxt'
|
import { getNuxtAppCtx, useNuxtApp } from '../nuxt'
|
||||||
import { useAsyncData } from './asyncData'
|
import { useAsyncData } from './asyncData'
|
||||||
import { useRoute } from './router'
|
import { useRoute } from './router'
|
||||||
import { createError } from './error'
|
import { createError } from './error'
|
||||||
@ -32,7 +32,7 @@ async function runLegacyAsyncData (res: Record<string, any> | Promise<Record<str
|
|||||||
export const defineNuxtComponent: typeof defineComponent =
|
export const defineNuxtComponent: typeof defineComponent =
|
||||||
function defineNuxtComponent (...args: any[]): any {
|
function defineNuxtComponent (...args: any[]): any {
|
||||||
const [options, key] = args
|
const [options, key] = args
|
||||||
const { setup } = options
|
const { setup } = options as DefineComponent
|
||||||
|
|
||||||
// Avoid wrapping if no options api is used
|
// Avoid wrapping if no options api is used
|
||||||
if (!setup && !options.asyncData && !options.head) {
|
if (!setup && !options.asyncData && !options.head) {
|
||||||
@ -48,7 +48,18 @@ export const defineNuxtComponent: typeof defineComponent =
|
|||||||
...options,
|
...options,
|
||||||
setup (props, ctx) {
|
setup (props, ctx) {
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
const res = setup ? Promise.resolve(nuxtApp.runWithContext(() => setup(props, ctx))).then(r => r || {}) : {}
|
|
||||||
|
let res = {}
|
||||||
|
if (setup) {
|
||||||
|
const fn = (): Promise<Record<string, any>> => Promise.resolve(setup(props, ctx)).then((r: any) => r || {})
|
||||||
|
const nuxtAppCtx = getNuxtAppCtx(nuxtApp._id)
|
||||||
|
if (import.meta.server) {
|
||||||
|
res = nuxtAppCtx.callAsync(nuxtApp, fn)
|
||||||
|
} else {
|
||||||
|
nuxtAppCtx.set(nuxtApp)
|
||||||
|
res = fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const promises: Promise<any>[] = []
|
const promises: Promise<any>[] = []
|
||||||
if (options.asyncData) {
|
if (options.asyncData) {
|
||||||
|
@ -24,7 +24,7 @@ import type { RouteAnnouncer } from '../app/composables/route-announcer'
|
|||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { appId, chunkErrorEvent, multiApp } from '#build/nuxt.config.mjs'
|
import { appId, chunkErrorEvent, multiApp } from '#build/nuxt.config.mjs'
|
||||||
|
|
||||||
function getNuxtAppCtx (id = appId || 'nuxt-app') {
|
export function getNuxtAppCtx (id = appId || 'nuxt-app') {
|
||||||
return getContext<NuxtApp>(id, {
|
return getContext<NuxtApp>(id, {
|
||||||
asyncContext: !!__NUXT_ASYNC_CONTEXT__ && import.meta.server,
|
asyncContext: !!__NUXT_ASYNC_CONTEXT__ && import.meta.server,
|
||||||
})
|
})
|
||||||
|
@ -2862,14 +2862,28 @@ describe('lazy import components', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('defineNuxtComponent watch duplicate', () => {
|
describe('defineNuxtComponent', () => {
|
||||||
it('test after navigation duplicate', async () => {
|
it('watches duplicate updates after navigation', async () => {
|
||||||
const { page } = await renderPage('/define-nuxt-component')
|
const { page } = await renderPage('/define-nuxt-component')
|
||||||
await page.getByTestId('define-nuxt-component-bar').click()
|
await page.getByTestId('define-nuxt-component-bar').click()
|
||||||
await page.getByTestId('define-nuxt-component-state').click()
|
await page.getByTestId('define-nuxt-component-state').click()
|
||||||
await page.getByTestId('define-nuxt-component-foo').click()
|
await page.getByTestId('define-nuxt-component-foo').click()
|
||||||
expect(await page.getByTestId('define-nuxt-component-state').first().innerText()).toBe('2')
|
expect(await page.getByTestId('define-nuxt-component-state').first().innerText()).toBe('2')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('get correctly route when navigating between routes', async () => {
|
||||||
|
const { page } = await renderPage('/define-nuxt-component/route-1')
|
||||||
|
await page.getByText('Go to route 2').click()
|
||||||
|
expect(await page.getByTestId('define-nuxt-component-route-2-path').innerText()).include('route-2')
|
||||||
|
|
||||||
|
await page.getByText('Go to route 1').click()
|
||||||
|
expect(await page.getByTestId('define-nuxt-component-route-1-path').innerText()).include('route-1')
|
||||||
|
})
|
||||||
|
|
||||||
|
it ('should get correctly inject value', async () => {
|
||||||
|
const { page } = await renderPage('/define-nuxt-component/inject')
|
||||||
|
expect(await page.getByTestId('define-nuxt-component-inject-value').innerText()).include('bar')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('namespace access to useNuxtApp', () => {
|
describe('namespace access to useNuxtApp', () => {
|
||||||
|
7
test/fixtures/basic/pages/define-nuxt-component/inject.vue
vendored
Normal file
7
test/fixtures/basic/pages/define-nuxt-component/inject.vue
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
provide('foo', 'bar')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NuxtPage />
|
||||||
|
</template>
|
17
test/fixtures/basic/pages/define-nuxt-component/inject/index.vue
vendored
Normal file
17
test/fixtures/basic/pages/define-nuxt-component/inject/index.vue
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default defineNuxtComponent({
|
||||||
|
name: 'DefineNuxtComponentTest',
|
||||||
|
setup () {
|
||||||
|
const value = inject('foo')
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div data-testid="define-nuxt-component-inject-value">
|
||||||
|
{{ value }}
|
||||||
|
</div>
|
||||||
|
</template>
|
23
test/fixtures/basic/pages/define-nuxt-component/route-1.vue
vendored
Normal file
23
test/fixtures/basic/pages/define-nuxt-component/route-1.vue
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default defineNuxtComponent({
|
||||||
|
name: 'DefineNuxtComponentTest',
|
||||||
|
setup () {
|
||||||
|
const route = useRoute()
|
||||||
|
const path = route.path.toString()
|
||||||
|
|
||||||
|
return {
|
||||||
|
path,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>route-1</h1>
|
||||||
|
<NuxtLink to="/define-nuxt-component/route-2">Go to route 2</NuxtLink>
|
||||||
|
<div data-testid="define-nuxt-component-route-1-path">
|
||||||
|
{{ path }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
23
test/fixtures/basic/pages/define-nuxt-component/route-2.vue
vendored
Normal file
23
test/fixtures/basic/pages/define-nuxt-component/route-2.vue
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default defineNuxtComponent({
|
||||||
|
name: 'DefineNuxtComponentTest',
|
||||||
|
setup () {
|
||||||
|
const route = useRoute()
|
||||||
|
const path = route.path.toString()
|
||||||
|
|
||||||
|
return {
|
||||||
|
path,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>route-2</h2>
|
||||||
|
<NuxtLink to="/define-nuxt-component/route-1">Go to route 1</NuxtLink>
|
||||||
|
<div data-testid="define-nuxt-component-route-2-path">
|
||||||
|
{{ path }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
Loading…
Reference in New Issue
Block a user