Skip to main content

Vue Component Generator

Build Vue 3 <script setup> components with TypeScript-first props via defineProps<T>, typed emits via defineEmits, composables, and optional watch / provide-inject setup. Copy the generated .vue file and drop it into your project.

✓ defineProps + withDefaults ✓ Typed emits ✓ Composable imports

script setup vs Options API: Quick Comparison

Feature Options API script setup (Composition API)
Props props: { title: String } defineProps<{ title: string }>()
State data() { return { count: 0 } } const count = ref(0)
Computed computed: { doubled() { ... } } const doubled = computed(() => count.value * 2)
Methods methods: { increment() { } } function increment() { }
Lifecycle mounted() { } onMounted(() => { })
Logic reuse Mixins (fragile) Composables (explicit, type-safe)

Typed Props Pattern (Recommended)

{``}

Building a Composable

A composable extracts reactive logic into a reusable function. Here's a minimal useCounter pattern:

{`// composables/useCounter.ts
import { ref, computed } from 'vue';

export function useCounter(initial = 0) {
  const count = ref(initial);
  const doubled = computed(() => count.value * 2);

  function increment() { count.value++; }
  function reset() { count.value = initial; }

  return { count, doubled, increment, reset };
}

// In component:
// const { count, increment } = useCounter(10);`}

Component Best Practices

  • Always use lang="ts" — TypeScript catches prop type mismatches at compile time
  • Prefer defineProps<T>() over runtime props for full TypeScript inference
  • Default object/array props with factory functions: items: () => []
  • Name emits in kebab-case in templates (@my-event) but camelCase in defineEmits
  • Use <style scoped> — prevents style leakage between components
  • Extract logic over 30 lines into a composable in composables/

Frequently Asked Questions

What is Vue 3 Composition API and script setup?▼

`<script setup>` is the recommended way to write Vue 3 components. It's syntactic sugar over the Composition API that removes boilerplate: no `export default`, no explicit `setup()` function, and all top-level declarations are automatically exposed to the template. Variables defined with `ref()` or `reactive()` are directly usable in templates. It pairs perfectly with TypeScript using `defineProps<Props>()` and `defineEmits<Emits>()`.

How do I define props with TypeScript in script setup?▼

Use `defineProps<Props>()` with a TypeScript interface. For default values, wrap with `withDefaults()`: `const props = withDefaults(defineProps<{ title: string; count?: number }>(), { count: 0 })`. The `Props` interface is type-checked at compile time by the Vue compiler. Avoid mixing runtime props declaration (`defineProps({ title: String })`) with the type-based approach in the same component.

What is the difference between ref() and reactive()?▼

`ref()` wraps a value in a reactive container — access it via `.value` in script, but the template auto-unwraps it. Use `ref` for primitives (strings, numbers, booleans) and for reactive object references you might reassign. `reactive()` makes an entire object deeply reactive — no `.value` needed. Drawback: you can't destructure a reactive() object without losing reactivity (use `toRefs()` to fix this). Stick with `ref` for most cases.

When should I use watch() vs watchEffect()?▼

`watch(source, callback)` runs only when the specific source changes, giving you both old and new values. It's lazy by default (doesn't run on mount). `watchEffect(callback)` tracks all reactive dependencies accessed inside it and runs immediately — similar to Svelte's $effect. Use `watch` when you need old values or want precise control over what triggers the watcher. Use `watchEffect` for effects that should run once immediately and re-run when any dependency changes.

What is a Vue composable and how should I structure one?▼

A composable is a function that uses the Composition API to encapsulate and reuse stateful logic. Name it with a `use` prefix (e.g., `useCounter`, `useFetch`). Return reactive state and methods as a plain object. Composables are called at the top level of `<script setup>` (not inside conditions or loops) so Vue can properly track their lifecycle. Libraries like VueUse provide hundreds of production-ready composables.

How do provide/inject work in Vue 3?▼

provide/inject is Vue's dependency injection — the ancestor-to-descendant alternative to prop drilling. A parent calls `provide('key', value)` to make a value available to all descendants. A descendant calls `const val = inject('key')` to receive it. For type safety, use InjectionKey: `const countKey: InjectionKey<Ref<number>> = Symbol('count')`. inject() accepts a default value as the second argument.

Share this tool: X / Twitter LinkedIn
✓ 60,000+ developers use DevPlaybook ★★★★★ 4.8 / 5 on Gumroad ✓ MIT licensed · Instant download ✓ No login required

Related Products

on Gumroad

You Might Also Need

More Free Tools

Enjoying this tool? Get more like it.

Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.

DevPlaybook Pro 7 days free

Unlock AI-Powered Dev Tools

  • ⚡ AI Code Review, Doc Generator & SQL Builder
  • ⚡ All premium templates & early access
  • ⚡ Member discounts on Gumroad products
Start Free Trial →

$9/mo after trial · Cancel anytime

Want the full toolkit?

Get DevPlaybook Pro

Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.

$79
$241 separately Save $162 (67% off)
Get DevPlaybook Pro — $79 →

MIT licensed · Instant download · No subscription

See what's included → Browse all deals →