--- name: script-setup-macros description: Vue 3 script setup syntax and compiler macros for defining props, emits, models, and more --- # Script Setup & Macros ` ``` ## defineProps Declare component props with full TypeScript support. ```ts // Type-based declaration (recommended) const props = defineProps<{ title: string count?: number items: string[] }>() // With defaults (Vue 3.5+) const { title, count = 0 } = defineProps<{ title: string count?: number }>() // With defaults (Vue 3.4 and below) const props = withDefaults(defineProps<{ title: string items?: string[] }>(), { items: () => [] // Use factory for arrays/objects }) ``` ## defineEmits Declare emitted events with typed payloads. ```ts // Named tuple syntax (recommended) const emit = defineEmits<{ update: [value: string] change: [id: number, name: string] close: [] }>() emit('update', 'new value') emit('change', 1, 'name') emit('close') ``` ## defineModel Two-way binding prop consumed via `v-model`. Available in Vue 3.4+. ```ts // Basic usage - creates "modelValue" prop const model = defineModel() model.value = 'hello' // Emits "update:modelValue" // Named model - consumed via v-model:name const count = defineModel('count', { default: 0 }) // With modifiers const [value, modifiers] = defineModel() if (modifiers.trim) { // Handle trim modifier } // With transformers const [value, modifiers] = defineModel({ get(val) { return val?.toLowerCase() }, set(val) { return modifiers.trim ? val?.trim() : val } }) ``` Parent usage: ```vue ``` ## defineExpose Explicitly expose properties to parent via template refs. Components are closed by default. ```ts import { ref } from 'vue' const count = ref(0) const reset = () => { count.value = 0 } defineExpose({ count, reset }) ``` Parent access: ```ts const childRef = ref<{ count: number; reset: () => void }>() childRef.value?.reset() ``` ## defineOptions Declare component options without a separate ` ``` Multiple generics with constraints: ```vue ``` ## Local Custom Directives Use `vNameOfDirective` naming convention. ```ts const vFocus = { mounted: (el: HTMLElement) => el.focus() } // Or import and rename import { myDirective as vMyDirective } from './directives' ``` ```vue ``` ## Top-level await Use `await` directly in ` ```