使用 Vue & UI Pro 的仪表板模板

components

components/ 目录是存放所有 Vue 组件的地方。

Nuxt 会自动导入此目录中的所有组件(以及您可能使用的任何模块注册的组件)。

目录结构
| components/
--| AppHeader.vue
--| AppFooter.vue
app.vue
<template>
  <div>
    <AppHeader />
    <NuxtPage />
    <AppFooter />
  </div>
</template>

组件名称

如果您在嵌套目录中有一个组件,例如

目录结构
| components/
--| base/
----| foo/
------| Button.vue

... 那么组件的名称将基于其自身的路径目录和文件名,重复的段将被删除。因此,组件的名称将是

<BaseFooButton />
为了清晰起见,我们建议组件的文件名与其名称匹配。因此,在上面的示例中,您可以将 Button.vue 重命名为 BaseFooButton.vue

如果您想仅根据组件的名称(而不是路径)自动导入组件,则需要使用扩展形式的配置对象将 pathPrefix 选项设置为 false

nuxt.config.ts
export default 
defineNuxtConfig
({
components
: [
{
path
: '~/components',
pathPrefix
: false,
}, ], });

这将使用 Nuxt 2 中使用的相同策略注册组件。例如,~/components/Some/MyComponent.vue 将可用作 <MyComponent> 而不是 <SomeMyComponent>

动态组件

如果您想使用 Vue <component :is="someComputedComponent"> 语法,您需要使用 Vue 提供的 resolveComponent 帮助程序,或者直接从 #components 导入组件,并将其传递到 is 属性中。

例如

pages/index.vue
<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 包大小。

pages/index.vue
<script setup lang="ts">
const show = ref(false)
</script>

<template>
  <div>
    <h1>Mountains</h1>
    <LazyMountainsList v-if="show" />
    <button v-if="!show" @click="show = true">Show List</button>
  </div>
</template>

直接导入

如果您希望或需要绕过 Nuxt 的自动导入功能,也可以从 #components 显式导入组件。

pages/index.vue
<script setup lang="ts">
import { NuxtLink, LazyMountainsList } from '#components'

const show = ref(false)
</script>

<template>
  <div>
    <h1>Mountains</h1>
    <LazyMountainsList v-if="show" />
    <button v-if="!show" @click="show = true">Show List</button>
    <NuxtLink to="/">Home</NuxtLink>
  </div>
</template>

自定义目录

默认情况下,仅扫描 ~/components 目录。如果您想添加其他目录,或更改此目录子文件夹中组件的扫描方式,您可以将其他目录添加到配置中。

nuxt.config.ts
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' },
// It's important that this comes last if you have overrides you wish to apply // to sub-directories of `~/components`. // // ~/components/Btn.vue => <Btn /> // ~/components/base/Btn.vue => <BaseBtn /> '~/components' ] })

npm 包

如果您想从 npm 包中自动导入组件,您可以在 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.tsextensions 键中指定的任何文件都将被视为组件。如果您需要限制应注册为组件的文件扩展名,可以使用组件目录声明的扩展形式及其 extensions 键。

客户端组件

如果组件仅用于客户端渲染,则可以在组件中添加 .client 后缀。

目录结构
| components/
--| Comments.client.vue
pages/example.vue
<template>
  <div>
    <!-- this component will only be rendered on client side -->
    <Comments />
  </div>
</template>
此功能仅适用于 Nuxt 自动导入和 #components 导入。从其真实路径显式导入这些组件不会将它们转换为仅客户端组件。
.client 组件仅在挂载后才会渲染。要使用 onMounted() 访问渲染后的模板,请在 onMounted() 钩子的回调中添加 await nextTick()
您也可以使用 <ClientOnly> 组件实现类似的结果。

服务器组件

服务器组件允许在您的客户端应用程序中服务器渲染单个组件。即使您正在生成静态站点,也可以在 Nuxt 中使用服务器组件。这使得构建复杂的站点成为可能,这些站点混合了动态组件、服务器渲染的 HTML 甚至静态的标记块。

服务器组件可以单独使用,也可以与 客户端组件 配合使用。

观看关于 Nuxt 服务器组件的 Learn Vue 视频。
阅读 Daniel Roe 关于 Nuxt 服务器组件的指南。

独立服务器组件

独立服务器组件始终在服务器上渲染,也称为“岛屿组件”。

当它们的 props 更新时,将导致一个网络请求,该请求将更新已渲染的 HTML 内容。

服务器组件目前处于实验阶段,要使用它们,您需要在 `nuxt.config` 中启用“组件岛屿”功能。

nuxt.config.ts
export default 
defineNuxtConfig
({
experimental
: {
componentIslands
: true
} })

现在,您可以使用 `.server` 后缀注册仅服务器组件,并在应用程序中的任何地方自动使用它们。

目录结构
| components/
--| HighlightedMarkdown.server.vue
pages/example.vue
<template>
  <div>
    <!--
      this will automatically be rendered on the server, meaning your markdown parsing + highlighting
      libraries are not included in your client bundle.
     -->
    <HighlightedMarkdown markdown="# Headline" />
  </div>
</template>

仅服务器组件在内部使用 `<NuxtIsland>`,这意味着 `lazy` 属性和 `#fallback` 插槽都将传递给它。

服务器组件(和岛屿)必须具有单个根元素。(HTML 注释也被视为元素。)
大多数仅服务器组件和岛屿组件的功能,例如插槽和客户端组件,仅适用于单文件组件。

服务器组件中的客户端组件

此功能需要在您的配置中将 `experimental.componentIslands.selectiveClient` 设置为 `true`。

您可以通过在要以客户端方式加载的组件上设置 `nuxt-client` 属性来部分地水化组件。

components/ServerWithClient.vue
<template>
  <div>
    <HighlightedMarkdown markdown="# Headline" />
    <!-- Counter will be loaded and hydrated client-side -->
    <Counter nuxt-client :count="5" />
  </div>
</template>
这仅在服务器组件中有效。客户端组件的插槽仅在将 `experimental.componentIsland.selectiveClient` 设置为 `'deep'` 时有效,并且由于它们是在服务器端渲染的,因此在客户端它们不可交互。

服务器组件上下文

渲染仅服务器或岛屿组件时,`<NuxtIsland>` 会发出一个获取请求,该请求会返回一个 `NuxtIslandResponse`。(如果在服务器上渲染,这是一个内部请求,或者如果您在客户端导航上渲染,则可以在网络选项卡中看到该请求。)

这意味着

  • 将在服务器端创建一个新的 Vue 应用程序来创建 `NuxtIslandResponse`。
  • 在渲染组件时将创建一个新的“岛屿上下文”。
  • 您无法从应用程序的其余部分访问“岛屿上下文”,也无法从岛屿组件访问应用程序其余部分的上下文。换句话说,服务器组件或岛屿与应用程序的其余部分是隔离的
  • 您的插件将在渲染岛屿时再次运行,除非它们已设置 `env: { islands: false }`(您可以在对象语法插件中执行此操作)。

在岛屿组件内部,您可以通过 nuxtApp.ssrContext.islandContext 访问其岛屿上下文。请注意,虽然岛屿组件仍被标记为实验性,但此上下文的格式可能会发生变化。

插槽可以是交互式的,并被包装在一个带有 display: contents;<div> 中。

与客户端组件配对

在这种情况下,.server + .client 组件是组件的两个“半部分”,可以在高级用例中用于在服务器端和客户端端分别实现组件。

目录结构
| components/
--| Comments.client.vue
--| Comments.server.vue
pages/example.vue
<template>
  <div>
    <!-- this component will render Comments.server on the server then Comments.client once mounted in the browser -->
    <Comments />
  </div>
</template>

内置 Nuxt 组件

Nuxt 提供了许多组件,包括 <ClientOnly><DevOnly>。您可以在 API 文档中了解更多关于它们的信息。

文档 > 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
)
// Add ./components dir to the list
dirs
.
push
({
path
:
resolve
('./components'),
prefix
: 'awesome'
}) } } })

就是这样!现在,在您的项目中,您可以在您的 nuxt.config 文件中将您的 UI 库作为 Nuxt 模块导入

nuxt.config.ts
export default 
defineNuxtConfig
({
modules
: ['awesome-ui/nuxt']
})

... 并直接在我们的 pages/index.vue 中使用模块组件(以 awesome- 为前缀)。

<template>
  <div>
    My <AwesomeButton>UI button</AwesomeButton>!
    <awesome-alert>Here's an alert!</awesome-alert>
  </div>
</template>

它将仅在使用时自动导入组件,并在更新 node_modules/awesome-ui/components/ 中的组件时支持 HMR。

文档 > 示例 > 功能 > 自动导入 中阅读和编辑一个实时示例。