mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 05:35:13 +00:00
refactor(nuxt)!: move head
option support into defineNuxtComponent
(#8901)
This commit is contained in:
parent
dfce660875
commit
2c2fbdffc9
@ -5,10 +5,10 @@ description: defineNuxtComponent() is a helper function for defining type safe c
|
||||
|
||||
# `defineNuxtComponent`
|
||||
|
||||
`defineNuxtComponent()` is a helper function for defining type safe Vue components using options API similar to [defineComponent()](https://vuejs.org/api/general.html#definecomponent). `defineNuxtComponent()` wrapper also adds support for `asyncData` component option.
|
||||
`defineNuxtComponent()` is a helper function for defining type safe Vue components using options API similar to [defineComponent()](https://vuejs.org/api/general.html#definecomponent). `defineNuxtComponent()` wrapper also adds support for `asyncData` and `head` component options.
|
||||
|
||||
::alert{type=warning}
|
||||
Options API support for `asyncData` may well change before the stable release of Nuxt 3.
|
||||
Options API support for `asyncData` and `head` may well change before the stable release of Nuxt 3.
|
||||
::
|
||||
|
||||
::Alert
|
||||
@ -34,3 +34,19 @@ export default defineNuxtComponent({
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
## `head()`
|
||||
|
||||
If you choose not to use `setup()` in your app, you can use the `head()` method within your component definition:
|
||||
|
||||
```vue [pages/index.vue]
|
||||
<script lang="ts">
|
||||
export default defineNuxtComponent({
|
||||
head(nuxtApp) {
|
||||
return {
|
||||
title: 'My site'
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
@ -4,6 +4,9 @@ import { NuxtApp, useNuxtApp } from '../nuxt'
|
||||
import { useAsyncData } from './asyncData'
|
||||
import { useRoute } from './router'
|
||||
|
||||
// eslint-disable-next-line import/no-restricted-paths
|
||||
import { useHead } from '#head'
|
||||
|
||||
export const NuxtComponentIndicator = '__nuxt_component'
|
||||
|
||||
async function runLegacyAsyncData (res: Record<string, any> | Promise<Record<string, any>>, fn: (nuxtApp: NuxtApp) => Promise<Record<string, any>>) {
|
||||
@ -25,7 +28,7 @@ export const defineNuxtComponent: typeof defineComponent =
|
||||
const { setup } = options
|
||||
|
||||
// Avoid wrapping if no options api is used
|
||||
if (!setup && !options.asyncData) {
|
||||
if (!setup && !options.asyncData && !options.head) {
|
||||
return {
|
||||
[NuxtComponentIndicator]: true,
|
||||
...options
|
||||
@ -43,6 +46,11 @@ export const defineNuxtComponent: typeof defineComponent =
|
||||
promises.push(runLegacyAsyncData(res, options.asyncData))
|
||||
}
|
||||
|
||||
if (options.head) {
|
||||
const nuxtApp = useNuxtApp()
|
||||
useHead(typeof options.head === 'function' ? () => options.head(nuxtApp) : options.head)
|
||||
}
|
||||
|
||||
return Promise.resolve(res)
|
||||
.then(() => Promise.all(promises))
|
||||
.then(() => res)
|
||||
|
@ -10,7 +10,7 @@ export type { PageMeta } from '../pages/runtime'
|
||||
// eslint-disable-next-line import/no-restricted-paths
|
||||
export type { MetaObject } from '../head/runtime'
|
||||
// eslint-disable-next-line import/no-restricted-paths
|
||||
export { useHead, useMeta } from '#head'
|
||||
export { useHead } from '#head'
|
||||
|
||||
export const isVue2 = false
|
||||
export const isVue3 = true
|
||||
|
@ -29,9 +29,6 @@ export default defineNuxtModule({
|
||||
})
|
||||
}
|
||||
|
||||
// Add mixin plugin
|
||||
addPlugin({ src: resolve(runtimeDir, 'mixin-plugin') })
|
||||
|
||||
// Add library specific plugin
|
||||
addPlugin({ src: resolve(runtimeDir, 'lib/vueuse-head.plugin') })
|
||||
}
|
||||
|
@ -12,9 +12,3 @@ import { useNuxtApp } from '#app'
|
||||
export function useHead (meta: MaybeComputedRef<MetaObject>) {
|
||||
useNuxtApp()._useHead(meta)
|
||||
}
|
||||
|
||||
// TODO: remove useMeta support when Nuxt 3 is stable
|
||||
/** @deprecated Please use new `useHead` composable instead */
|
||||
export function useMeta (meta: MaybeComputedRef<MetaObject>) {
|
||||
return useHead(meta)
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import { useHead } from './composables'
|
||||
import { defineNuxtPlugin, useNuxtApp } from '#app'
|
||||
|
||||
const metaMixin = {
|
||||
created () {
|
||||
const instance = getCurrentInstance()
|
||||
if (!instance) { return }
|
||||
|
||||
const options = instance.type
|
||||
if (!options || !('head' in options)) { return }
|
||||
|
||||
const nuxtApp = useNuxtApp()
|
||||
const source = typeof options.head === 'function'
|
||||
? () => options.head(nuxtApp)
|
||||
: options.head
|
||||
|
||||
useHead(source)
|
||||
}
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
nuxtApp.vueApp.mixin(metaMixin)
|
||||
})
|
@ -5,8 +5,7 @@ const commonPresets: InlinePreset[] = [
|
||||
defineUnimportPreset({
|
||||
from: '#head',
|
||||
imports: [
|
||||
'useHead',
|
||||
'useMeta'
|
||||
'useHead'
|
||||
]
|
||||
}),
|
||||
// vue-demi (mocked)
|
||||
|
@ -253,7 +253,6 @@ describe('head tags', () => {
|
||||
expect(headHtml).toContain('<meta name="description" content="overriding with an inline useHead call">')
|
||||
expect(headHtml).toMatch(/<html[^>]*class="html-attrs-test"/)
|
||||
expect(headHtml).toMatch(/<body[^>]*class="body-attrs-test"/)
|
||||
expect(headHtml).toContain('script>console.log("works with useMeta too")</script>')
|
||||
expect(headHtml).toContain('<script src="https://a-body-appended-script.com" data-meta-body></script></body>')
|
||||
|
||||
const indexHtml = await $fetch('/')
|
||||
|
@ -29,6 +29,7 @@ describe.skipIf(isWindows)('minimal nuxt application', () => {
|
||||
expect(stats.client.totalBytes).toBeLessThan(110000)
|
||||
expect(stats.client.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
|
||||
[
|
||||
"_nuxt/composables.js",
|
||||
"_nuxt/entry.js",
|
||||
"_nuxt/error-404.js",
|
||||
"_nuxt/error-500.js",
|
||||
|
45
test/fixtures/basic/pages/head.vue
vendored
45
test/fixtures/basic/pages/head.vue
vendored
@ -1,35 +1,32 @@
|
||||
<script setup>
|
||||
const a = ref('')
|
||||
|
||||
useHead({
|
||||
// title template function example
|
||||
titleTemplate: title => `${title} - Title Template Fn Change`,
|
||||
bodyAttrs: {
|
||||
class: 'body-attrs-test'
|
||||
},
|
||||
script: [
|
||||
{
|
||||
src: 'https://a-body-appended-script.com',
|
||||
body: true
|
||||
}
|
||||
],
|
||||
meta: [{ name: 'description', content: 'first' }]
|
||||
})
|
||||
useHead({ meta: [{ charset: 'utf-16' }, { name: 'description', content: computed(() => `${a.value} with an inline useHead call`) }] })
|
||||
useMeta({ script: [{ children: 'console.log("works with useMeta too")' }] })
|
||||
a.value = 'overriding'
|
||||
</script>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
export default defineNuxtComponent({
|
||||
head () {
|
||||
return {
|
||||
htmlAttrs: {
|
||||
class: 'html-attrs-test'
|
||||
}
|
||||
}
|
||||
},
|
||||
setup () {
|
||||
const a = ref('')
|
||||
useHead({
|
||||
// title template function example
|
||||
titleTemplate: title => `${title} - Title Template Fn Change`,
|
||||
bodyAttrs: {
|
||||
class: 'body-attrs-test'
|
||||
},
|
||||
script: [
|
||||
{
|
||||
src: 'https://a-body-appended-script.com',
|
||||
body: true
|
||||
}
|
||||
],
|
||||
meta: [{ name: 'description', content: 'first' }]
|
||||
})
|
||||
useHead({ meta: [{ charset: 'utf-16' }, { name: 'description', content: computed(() => `${a.value} with an inline useHead call`) }] })
|
||||
a.value = 'overriding'
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
Loading…
Reference in New Issue
Block a user