Last updated
What Does the Vue Component Generator Do?
The Vue Component Generator creates Vue.js component boilerplate with configurable options: Composition API or Options API, Vue 2 or Vue 3, TypeScript support, props, emits, and scoped styles. It eliminates repetitive setup and ensures consistent component structure across your project.
Vue 3 Composition API (script setup) — Basic Component
<!-- UserCard.vue -->
<template>
<div class="user-card">
<h2>{{ user.name }}</h2>
<p>{{ user.email }}</p>
<button @click="handleClick">View Profile</button>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const props = defineProps({
user: {
type: Object,
required: true
},
showActions: {
type: Boolean,
default: true
}
});
const emit = defineEmits(['click', 'update']);
const isActive = ref(false);
const displayName = computed(() => props.user.name.toUpperCase());
function handleClick() {
isActive.value = !isActive.value;
emit('click', props.user);
}
</script>
<style scoped>
.user-card {
padding: 1rem;
border: 1px solid #e2e8f0;
border-radius: 0.5rem;
}
</style>
Vue 3 Composition API with TypeScript
<!-- ProductCard.vue -->
<template>
<div class="product-card">
<img :src="product.imageUrl" :alt="product.name" />
<h3>{{ product.name }}</h3>
<p class="price">{{ formattedPrice }}</p>
<button @click="addToCart">Add to Cart</button>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
interface Product {
id: number;
name: string;
price: number;
imageUrl: string;
}
const props = defineProps<{
product: Product;
currency?: string;
}>();
const emit = defineEmits<{
addToCart: [product: Product];
wishlist: [productId: number];
}>();
const formattedPrice = computed(() => {
const currency = props.currency ?? 'USD';
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency
}).format(props.product.price);
});
function addToCart() {
emit('addToCart', props.product);
}
</script>
<style scoped>
.product-card { ... }
.price { font-weight: bold; color: #2d3748; }
</style>
Vue 3 Options API Component
<!-- SearchBar.vue -->
<template>
<div class="search-bar">
<input
v-model="query"
type="text"
:placeholder="placeholder"
@keyup.enter="search"
/>
<button @click="search" :disabled="isLoading">
{{ isLoading ? 'Searching...' : 'Search' }}
</button>
</div>
</template>
<script>
export default {
name: 'SearchBar',
props: {
placeholder: {
type: String,
default: 'Search...'
},
initialQuery: {
type: String,
default: ''
}
},
emits: ['search', 'clear'],
data() {
return {
query: this.initialQuery,
isLoading: false
};
},
computed: {
hasQuery() {
return this.query.trim().length > 0;
}
},
methods: {
async search() {
if (!this.hasQuery) return;
this.isLoading = true;
this.$emit('search', this.query.trim());
this.isLoading = false;
},
clear() {
this.query = '';
this.$emit('clear');
}
},
mounted() {
console.log('SearchBar mounted');
}
};
</script>
Vue 2 Component
<!-- LegacyModal.vue (Vue 2) -->
<template>
<div v-if="visible" class="modal-overlay" @click.self="close">
<div class="modal">
<slot />
<button @click="close">Close</button>
</div>
</div>
</template>
<script>
export default {
name: 'LegacyModal',
props: {
visible: {
type: Boolean,
default: false
}
},
methods: {
close() {
this.$emit('update:visible', false);
this.$emit('close');
}
}
};
</script>
Component with Pinia Store Integration
<!-- CartButton.vue -->
<script setup lang="ts">
import { useCartStore } from '@/stores/cart';
const cart = useCartStore();
</script>
<template>
<button @click="cart.toggleCart">
Cart ({{ cart.itemCount }})
</button>
</template>
<!-- stores/cart.ts (generated alongside component) -->
import { defineStore } from 'pinia';
export const useCartStore = defineStore('cart', {
state: () => ({
items: [] as CartItem[],
isOpen: false
}),
getters: {
itemCount: (state) => state.items.length
},
actions: {
toggleCart() {
this.isOpen = !this.isOpen;
}
}
});
Component with CSS Modules
<template>
<div :class="$style.container">
<h1 :class="$style.title">{{ title }}</h1>
</div>
</template>
<script setup>
defineProps({ title: String });
</script>
<style module>
.container {
max-width: 1200px;
margin: 0 auto;
}
.title {
font-size: 2rem;
color: #1a202c;
}
</style>
Generated Unit Test Scaffold
// UserCard.test.ts
import { mount } from '@vue/test-utils';
import { describe, it, expect, vi } from 'vitest';
import UserCard from './UserCard.vue';
const mockUser = {
id: 1,
name: 'Jane Doe',
email: 'jane@example.com'
};
describe('UserCard', () => {
it('renders user name', () => {
const wrapper = mount(UserCard, {
props: { user: mockUser }
});
expect(wrapper.text()).toContain('Jane Doe');
});
it('emits click event when button clicked', async () => {
const wrapper = mount(UserCard, {
props: { user: mockUser }
});
await wrapper.find('button').trigger('click');
expect(wrapper.emitted('click')).toBeTruthy();
expect(wrapper.emitted('click')[0]).toEqual([mockUser]);
});
});
Common Use Cases
- Scaffolding new components with consistent structure across a project
- Onboarding new team members with correct Vue conventions
- Migrating from Options API to Composition API
- Adding TypeScript to existing Vue components
- Generating component + store + test file together