---
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 `
```