Nuxt Components — Auto-Importing and Reusable Vue Components
In this tutorial, you will learn about Nuxt Components. We cover key concepts, practical examples, and best practices to help you master this topic.
Learn Nuxt 3 component system: auto-imports, component naming conventions, and building reusable UI components without manual registration.
In this lesson, you'll understand how Nuxt 3 auto-imports components, naming conventions, and component organization.
What You'll Learn
How Nuxt auto-imports components, naming conventions for multi-word components, component directories, and Lazy Loading.
Why It Matters
Auto-imports eliminate repetitive import statements. Components are available everywhere without manual registration, speeding up development.
flowchart LR
A[components/] --> B[Auto-imported]
A --> C[Available Globally]
B --> D[NuxtAppHeader]
B --> E[BlogPostCard]
B --> F[BaseButton]
C --> G[Any Page or Component]
style A fill:#00dc82,color:#fff
Basic Component
Create components/AppHeader.vue:
<template>
<header>
<NuxtLink to="/">Home</NuxtLink>
<slot />
</header>
</template>
Use it anywhere without import:
<!-- pages/index.vue -->
<template>
<div>
<AppHeader />
<h1>Home Page</h1>
</div>
</template>
Output: The component renders automatically. No import statement needed.
Nested Components
Organize components in subdirectories:
components/
├── base/
│ ├── BaseButton.vue
│ ├── BaseInput.vue
│ └── BaseCard.vue
├── blog/
│ ├── BlogPostCard.vue
│ └── BlogSidebar.vue
└── AppHeader.vue
Usage with directory prefix:
<template>
<div>
<BaseButton variant="primary">Click</BaseButton>
<BlogPostCard :post="post" />
</div>
</template>
Output: Nuxt prefixes component names with directory names. components/base/BaseButton.vue becomes <BaseButton>.
Lazy Loading
Lazy-load non-critical components:
<template>
<div>
<h1>Dashboard</h1>
<!-- This component loads only when visible -->
<LazyDashboardChart />
<!-- Conditional lazy loading -->
<LazyAdminPanel v-if="user.isAdmin" />
</div>
</template>
Output: Components prefixed with Lazy are loaded asynchronously, reducing initial bundle size.
Dynamic Components
Render components dynamically:
<script setup>
const { data: sections } = await useFetch('/api/sections');
</script>
<template>
<div>
<component
v-for="section in sections"
:is="section.component"
:key="section.id"
v-bind="section.props"
/>
</div>
</template>
Component Props and Emits
<!-- components/UserCard.vue -->
<script setup>
const props = defineProps({
user: { type: Object, required: true },
variant: { type: String, default: 'default' }
});
const emit = defineEmits(['select', 'delete']);
const handleSelect = () => emit('select', props.user.id);
</script>
<template>
<div class="card" :class="variant" @click="handleSelect">
<img :src="user.avatar" :alt="user.name" />
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
<button @click="$emit('delete', user.id)">Delete</button>
</div>
</template>
Common Mistakes
- Using single-word component names: Components like
Button.vuemight conflict with HTML elements. Use multi-word names:BaseButton.vue. - Not using directory prefixes correctly:
components/ui/Button.vuebecomes<UiButton>, not<Button>. - Forgetting
Lazyprefix for Code Splitting: WithoutLazy, components are eagerly loaded in the main bundle. - Over-nesting directories: Deep directory trees create long component names. Limit to 2-3 levels.
- Not using
<script setup>: Nuxt 3 and Vue 3 favor<script setup>for Composition API. Options API works but is less idiomatic.
Practice Questions
How are components in Nuxt 3 auto-imported? Answer: Any
.vuefile incomponents/is automatically available globally. No manual import or registration needed.How do you lazy-load a component? Answer: Prefix the component name with
Lazy:<LazyComponentName />. It loads asynchronously when needed.How are components in subdirectories referenced? Answer: Using directory names as prefix:
components/blog/PostCard.vuebecomes<BlogPostCard>.What is the purpose of
<script setup>? Answer: It's a compile-time syntax that reduces boilerplate for Composition API. Props, emits, and reactive data are declared concisely.
Challenge
Create a component library with: BaseButton, BaseInput, BaseCard, BaseModal, and BaseBadge. Use subdirectories for organization. Lazy-load the modal component.
Mini Project
Build a reusable UI kit with 10+ components organized in subdirectories (base, layout, form, data-display). Use auto-imports, lazy loading for heavy components, and demonstrate dynamic component rendering.
FAQ
What's Next
Learn about Nuxt Composables to understand auto-imported composables and state management in Nuxt 3.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro