Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 Composition API reference—script setup macros, reactivity, lifecycle hooks, and built-in components
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/script-setup-macros.md
1---2name: script-setup-macros3description: Vue 3 script setup syntax and compiler macros for defining props, emits, models, and more4---56# Script Setup & Macros78`<script setup>` is the recommended syntax for Vue SFCs with Composition API. It provides better runtime performance and IDE type inference.910## Basic Syntax1112```vue13<script setup lang="ts">14// Top-level bindings are exposed to template15import { ref } from 'vue'16import MyComponent from './MyComponent.vue'1718const count = ref(0)19const increment = () => count.value++20</script>2122<template>23<button @click="increment">{{ count }}</button>24<MyComponent />25</template>26```2728## defineProps2930Declare component props with full TypeScript support.3132```ts33// Type-based declaration (recommended)34const props = defineProps<{35title: string36count?: number37items: string[]38}>()3940// With defaults (Vue 3.5+)41const { title, count = 0 } = defineProps<{42title: string43count?: number44}>()4546// With defaults (Vue 3.4 and below)47const props = withDefaults(defineProps<{48title: string49items?: string[]50}>(), {51items: () => [] // Use factory for arrays/objects52})53```5455## defineEmits5657Declare emitted events with typed payloads.5859```ts60// Named tuple syntax (recommended)61const emit = defineEmits<{62update: [value: string]63change: [id: number, name: string]64close: []65}>()6667emit('update', 'new value')68emit('change', 1, 'name')69emit('close')70```7172## defineModel7374Two-way binding prop consumed via `v-model`. Available in Vue 3.4+.7576```ts77// Basic usage - creates "modelValue" prop78const model = defineModel<string>()79model.value = 'hello' // Emits "update:modelValue"8081// Named model - consumed via v-model:name82const count = defineModel<number>('count', { default: 0 })8384// With modifiers85const [value, modifiers] = defineModel<string>()86if (modifiers.trim) {87// Handle trim modifier88}8990// With transformers91const [value, modifiers] = defineModel({92get(val) { return val?.toLowerCase() },93set(val) { return modifiers.trim ? val?.trim() : val }94})95```9697Parent usage:98```vue99<Child v-model="name" />100<Child v-model:count="total" />101<Child v-model.trim="text" />102```103104## defineExpose105106Explicitly expose properties to parent via template refs. Components are closed by default.107108```ts109import { ref } from 'vue'110111const count = ref(0)112const reset = () => { count.value = 0 }113114defineExpose({115count,116reset117})118```119120Parent access:121```ts122const childRef = ref<{ count: number; reset: () => void }>()123childRef.value?.reset()124```125126## defineOptions127128Declare component options without a separate `<script>` block. Available in Vue 3.3+.129130```ts131defineOptions({132inheritAttrs: false,133name: 'CustomName'134})135```136137## defineSlots138139Provide type hints for slot props. Available in Vue 3.3+.140141```ts142const slots = defineSlots<{143default(props: { item: string; index: number }): any144header(props: { title: string }): any145}>()146```147148## Generic Components149150Declare generic type parameters using the `generic` attribute.151152```vue153<script setup lang="ts" generic="T extends string | number">154defineProps<{155items: T[]156selected: T157}>()158</script>159```160161Multiple generics with constraints:162```vue163<script setup lang="ts" generic="T, U extends Record<string, T>">164import type { Item } from './types'165defineProps<{166data: U167key: keyof U168}>()169</script>170```171172## Local Custom Directives173174Use `vNameOfDirective` naming convention.175176```ts177const vFocus = {178mounted: (el: HTMLElement) => el.focus()179}180181// Or import and rename182import { myDirective as vMyDirective } from './directives'183```184185```vue186<template>187<input v-focus />188</template>189```190191## Top-level await192193Use `await` directly in `<script setup>`. The component becomes async and must be used with `<Suspense>`.194195```vue196<script setup lang="ts">197const data = await fetch('/api/data').then(r => r.json())198</script>199```200201<!--202Source references:203- https://vuejs.org/api/sfc-script-setup.html204-->205