# Vue Components Patterns for Vue 3 components using Composition API with ` ``` ### With Options ```vue ``` **⚠️ Warning:** When using `default` without parent providing a value, parent and child can de-sync (parent `undefined`, child has default). Always provide matching defaults in parent or make prop required. **Prevent double-emit with `required: true`:** ```ts // ❌ Without required - emits twice (undefined then value) const model = defineModel() // ✅ With required - single emit const model = defineModel({ required: true }) ``` Use `required: true` when the model should always have a value to avoid the double-emit issue during initialization. ### Multiple Models Default assumes `modelValue` prop. For multiple bindings, use explicit names: ```vue ``` [v-model modifiers docs](https://vuejs.org/guide/components/v-model#handling-v-model-modifiers) ## Reusable Templates For typed, scoped template snippets within a component: ```vue ``` ## Template Refs (Vue 3.5+) Use `useTemplateRef()` for type-safe template references with IDE support: ```vue ``` **Benefits over `ref()`:** - Type-safe with generics - Better IDE autocomplete and refactoring - Explicit ref name as string literal **Dynamic refs:** ```vue ``` **Component refs with generics:** For generic components, use `ComponentExposed` from `vue-component-type-helpers`: ```ts import type { ComponentExposed } from 'vue-component-type-helpers' import MyGenericComponent from './MyGenericComponent.vue' // Get exposed methods/properties with correct generic types const compRef = useTemplateRef>('comp') onMounted(() => { compRef.value?.someExposedMethod() // Typed! }) ``` Install: `pnpm add -D vue-component-type-helpers` ## SSR Hydration (Vue 3.5+) **Suppress hydration mismatches** for values that differ between server/client: ```vue ``` **Generate SSR-stable IDs:** ```vue ``` ## Deferred Teleport (Vue 3.5+) Teleport to elements rendered later in the same cycle: ```vue ``` Without `defer`, teleport to `#late-div` would fail since it doesn't exist yet. ## Common Mistakes **Using `const props =` with destructured values:** ```ts // ❌ Wrong const props = defineProps<{ count: number }>() const { count } = props // Loses reactivity ``` **Forgetting TypeScript types:** ```ts // ❌ Wrong const emit = defineEmits(['update']) // ✅ Correct const emit = defineEmits<{ update: [id: number] }>() ``` **Components >300 lines:** Split into smaller components or extract logic to composables