components
Nuxt会自动导入此目录中的任何组件(以及您可能使用的任何模块注册的组件)。
-| components/
---| AppHeader.vue
---| AppFooter.vue
<template>
<div>
<AppHeader />
<NuxtPage />
<AppFooter />
</div>
</template>
组件名称
如果组件位于嵌套目录中,例如:
-| components/
---| base/
-----| foo/
-------| Button.vue
……那么组件的名称将基于其自己的路径目录和文件名,移除重复的片段。因此,组件的名称将是:
<BaseFooButton />
Button.vue
重命名为 BaseFooButton.vue
。如果您希望仅基于其名称而不是路径自动导入组件,那么您需要设置 pathPrefix
选项为 false
使用扩展形式的配置对象:
export default defineNuxtConfig({
components: [
{
path: '~/components',
pathPrefix: false, },
],
});
这将使用与Nuxt 2中使用相同的技术注册组件。例如,~/components/Some/MyComponent.vue
可以作为 <MyComponent>
使用,而不是 <SomeMyComponent>
。
动态组件
如果您想要使用 Vue <component :is="someComputedComponent">
语法,则需要使用 resolveComponent
由 Vue 提供或直接从 #components
导入组件并将其传递给 is
属性。
例如:
<script setup lang="ts">
import { SomeComponent } from '#components'
const MyButton = resolveComponent('MyButton')
</script>
<template>
<component :is="clickable ? MyButton : 'div'" />
<component :is="SomeComponent" />
</template>
resolveComponent
来处理动态组件,请确保不插入任何东西,只是组件的名称,它必须是字符串而不是变量。或者,虽然不推荐,您可以将所有组件全局注册,这将为您应用程序的所有组件创建异步块。
export default defineNuxtConfig({
components: {
+ global: true,
+ dirs: ['~/components']
},
})
您还可以选择性地将一些组件全局注册,方法是将它们放在 ~/components/global
目录中,或者使用 .global.vue
后缀在文件名中。如上所述,每个全局组件都是在单独的块中渲染的,因此请小心不要过度使用此功能。
global
选项也可以针对组件目录进行设置。动态导入
要动态导入组件(也称为懒加载组件),您只需在组件名称前添加 Lazy
前缀。这对于只有在需要时才希望使用组件的情况特别有用。
通过使用 Lazy
前缀,您可以延迟加载组件代码直到正确的时刻,这对于优化您的JavaScript包大小非常有帮助。
<script setup lang="ts">
const show = ref(false)
</script>
<template>
<div>
<h1>山脉</h1>
<LazyMountainsList v-if="show" />
<button v-if="!show" @click="show = true">显示列表</button>
</div>
</template>
直接导入
您也可以显式地从 #components
导入组件,如果您需要或需要绕过 Nuxt 的自动导入功能。
<script setup lang="ts">
import { NuxtLink, LazyMountainsList } from '#components'
const show = ref(false)
</script>
<template>
<div>
<h1>山脉</h1>
<LazyMountainsList v-if="show" />
<button v-if="!show" @click="show = true">显示列表</button>
<NuxtLink to="/">首页</NuxtLink>
</div>
</template>
自定义目录
默认情况下,仅扫描 ~/components
目录。如果您想添加其他目录,或者更改此目录子文件夹内组件的扫描方式,您可以在配置中添加其他目录:
export default defineNuxtConfig({
components: [
// ~/calendar-module/components/event/Update.vue => <EventUpdate />
{ path: '~/calendar-module/components' },
// ~/user-module/components/account/UserDeleteDialog.vue => <UserDeleteDialog />
{ path: '~/user-module/components', pathPrefix: false },
// ~/components/special-components/Btn.vue => <SpecialBtn />
{ path: '~/components/special-components', prefix: 'Special' },
// 如果您的配置中有任何覆盖您希望应用于 `~/components` 子目录的覆盖,则非常重要,
// 它需要在最后添加。
//
// ~/components/Btn.vue => <Btn />
// ~/components/base/Btn.vue => <BaseBtn />
'~/components'
]
})
npm 包
如果您想根据 npm 包自动导入组件,您可以在 本地模块 中使用 addComponent
提供的 addComponent
钩子来注册它们。
import { addComponent, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup() {
// import { MyComponent as MyAutoImportedComponent } from 'my-npm-package'
addComponent({
name: 'MyAutoImportedComponent',
export: 'MyComponent',
filePath: 'my-npm-package',
})
},
})
组件扩展
默认情况下,任何在 nuxt.config.ts 的 extensions
键中指定的扩展文件都被视为组件。
如果您需要限制应注册为组件的文件扩展名,您可以使用组件目录的扩展形式及其 extensions
键:
export default defineNuxtConfig({
components: [
{
path: '~/components',
extensions: ['.vue'], }
]
})
客户端组件
如果组件是仅在客户端渲染的,则可以在组件上添加 .client
后缀。
| components/
--| Comments.client.vue
<template>
<div>
<!-- 此组件仅在客户端渲染时才被渲染 -->
<Comments />
</div>
</template>
#components
导入时有效。如果显式从它们的真实路径导入这些组件,它们不会转换为仅客户端组件。.client
组件的渲染仅在挂载后发生。在 onMounted()
回调中使用 await nextTick()
以确保可以访问渲染的模板。服务器组件
服务器组件允许在您的客户端应用程序中渲染单个组件。即使您生成了一个静态网站,也可以在 Nuxt 中使用服务器组件。这意味着您可以构建混合动态组件、服务器端渲染的 HTML 甚至静态标记块的复杂站点。
服务器组件可以单独使用,也可以与 客户端组件 配对。
独立的服务器组件
独立的服务器组件将始终在服务器上渲染,也称为岛屿组件。
当它们的属性更新时,这将导致一个网络请求,该请求将更新渲染的 HTML。
服务器组件目前是实验性的,为了使用它们,您需要在 nuxt.config
中启用 '组件岛屿' 特性:
export default defineNuxtConfig({
experimental: {
componentIslands: true
}
})
现在您可以在 Nuxt 模块中注册仅服务器组件,使用 .server
后缀和在应用程序的任何地方使用它们。
-| components/
---| HighlightedMarkdown.server.vue
<template>
<div>
<!--
此组件将自动在服务器上渲染,这意味着您的 Markdown 解析加高亮显示
库不会包含在您的客户端包中。
-->
<HighlightedMarkdown markdown="# Headline" />
</div>
</template>
服务器组件在内部使用 <NuxtIsland>
,这意味着 lazy
属性和 #fallback
槽都传递给它。
客户组件在服务器组件内部
experimental.componentIslands.selectiveClient
在您的配置中为真。您可以通过在组件上设置 nuxt-client
属性来部分地水合组件,您希望它在客户端加载和水分化。
<template>
<div>
<HighlightedMarkdown markdown="# Headline" />
<!-- Counter 将只在浏览器中加载和水分化 -->
<Counter nuxt-client :count="5" />
</div>
</template>
experimental.componentIsland.selectiveClient
设置为 'deep'
,并且它们在客户端渲染时不是交互式的。服务器组件上下文
当渲染一个服务器或岛屿组件时,<NuxtIsland>
会发起一个 fetch 请求,该请求以 NuxtIslandResponse
返回。(如果您在服务器上渲染,这是内部请求,或者如果您是客户端导航,您可以在网络标签中看到它。)
这意味着:
- 一个新的 Vue 应用将在服务器上创建,以创建
NuxtIslandResponse
。 - 一个新的 '岛屿上下文' 将在渲染组件时创建。
- 您不能访问岛屿上下文,也不能访问岛屿上下文。换句话说,服务器组件或岛屿是 隔离 的。
- 您的插件将再次运行,当渲染岛屿时,除非他们有
env: { islands: false }
设置为真(您可以在对象语法插件中这样做)。
在岛屿组件内部,您可以通过 nuxtApp.ssrContext.islandContext
访问它的岛屿上下文。请注意,由于岛屿组件仍然是实验性的,这个上下文的格式可能会改变。
<div>
带有 display: contents;
与一个客户端组件配对
在这种情况下,.server
+ .client
组件是组件的两个“半”,并且可以用于高级用例,在服务器和客户端实现组件的分离实现。
-| components/
---| Comments.client.vue
---| Comments.server.vue
<template>
<div>
<!-- 此组件将在服务器上渲染 Comments.server,然后一旦浏览器中挂载,Comments.client -->
<Comments />
</div>
</template>
内置 Nuxt 组件
Nuxt 提供了一些组件,包括 <ClientOnly>
和 <DevOnly>
。您可以在 API 文档中阅读更多关于它们的信息。
库作者
创建一个具有自动树剪枝和组件注册的 Vue 组件库非常容易。✨
您可以使用 components:dirs
钩子扩展目录列表,而无需在 Nuxt 模块中要求用户配置。
想象一个目录结构如下:
-| node_modules/
---| awesome-ui/
-----| components/
-------| Alert.vue
-------| Button.vue
-----| nuxt.js
-| pages/
---| index.vue
-| nuxt.config.js
然后,在 awesome-ui/nuxt.js
中,您可以使用 components:dirs
钩子:
import { defineNuxtModule, createResolver } from '@nuxt/kit'
export default defineNuxtModule({
hooks: {
'components:dirs': (dirs) => {
const { resolve } = createResolver(import.meta.url)
// 添加 ./components 目录到列表
dirs.push({
path: resolve('./components'),
prefix: 'awesome'
})
}
}
})
就是这样!现在在你的项目中,你可以把你的 UI 库作为 Nuxt 模块在你的 nuxt.config
文件中导入:
export default defineNuxtConfig({
modules: ['awesome-ui/nuxt']
})
...并且直接在你的 pages/index.vue
中使用模块组件(带有 awesome-
前缀):
<template>
<div>
我的 <AwesomeButton>UI 按钮</AwesomeButton>!
<awesome-alert>这是一个警告!</awesome-alert>
</div>
</template>
它将自动导入组件,只有在使用时才会导入,并且在更新您的组件时也支持 HMR node_modules/awesome-ui/components/
。