Nuxt/docs/content/3.docs/2.directory-structure/4.components.md
2021-11-19 12:36:25 +01:00

4.1 KiB

icon title head.title
IconDirectory components Components directory

Components directory

The components/ directory is where you put all your Vue components which can then be imported inside your pages or other components (learn more).

Nuxt automatically imports any components in your components/ directory (along with components that are registered by any modules you may be using).

| components/
--| TheHeader.vue
--| TheFooter.vue
<template>
  <div>
    <TheHeader />
    <slot />
    <TheFooter />
  </div>
</template>

Component Names

If you have components in nested directories such as:

| components/
--| base/
----| foo/
------| Button.vue

The component name will be based on its own path directory and filename, with duplicate segments being removed. Therefore, the component will be:

<BaseFooButton />

::alert For clarity, it is recommended that the component file name matches its name. (So, in the example above, you could rename Button.vue to be BaseFooButton.vue.) ::

Dynamic Imports

To dynamically import a component (also known as lazy-loading a component) all you need to do is add the Lazy prefix to the component name.

<template>
  <div>
    <TheHeader />
    <slot />
    <LazyTheFooter />
  </div>
</template>

This is particularly useful if the component is not always needed. By using the Lazy prefix you can delay loading the component code until the right moment, which can be helpful for optimizing your JavaScript bundle size.

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

<script>
export default {
  data() {
    return {
      show: false
    }
  }
}
</script>

<ClientOnly> Component

Nuxt provides the <ClientOnly> component for purposely rendering a component only on client-side. To import a component only on the client, register the component in a client-side only plugin.

<template>
  <div>
    <Sidebar />
    <ClientOnly>
      <!-- this component will only be rendered on client-side -->
      <Comments />
    </ClientOnly>
  </div>
</template>

Use a slot as fallback until <ClientOnly> is mounted on client-side.

<template>
  <div>
    <Sidebar />
    <ClientOnly>
      <!-- this component will only be rendered on client-side -->
      <Comments />
      <template #fallback>
        <!-- this will be rendered on server-side -->
        <p>Loading comments...</p>
      </template>
    </ClientOnly>
  </div>
</template>

Library Authors

Making Vue component libraries with automatic tree-shaking and component registration is super easy

You can use the components:dirs hook to easily extend the directory list without requiring user configuration in your Nuxt module.

Imagine a directory structure like this:

| node_modules/
---| awesome-ui/
------| components/
---------| Alert.vue
---------| Button.vue
------| nuxt.js
| pages/
---| index.vue
| nuxt.config.js

Then in awesome-ui/nuxt.js you can use the components:dirs hook:

import { join } from 'pathe'
import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  hooks: {
    'components:dirs'(dirs) {
      // Add ./components dir to the list
      dirs.push({
        path: join(__dirname, 'components'),
        prefix: 'awesome'
      })
    }
  }
})

That's it! Now in your project, you can import your ui library as a Nuxt module in your nuxt.config.js:

export default {
  buildModules: ['awesome-ui/nuxt']
}

And directly use the module components (prefixed with awesome-), our pages/index.vue:

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

It will automatically import the components only if used and also support HMR when updating your components in node_modules/awesome-ui/components/.