setup()
The setup() function serves as the entry point for using the Composition API in components.
Component props. Props are reactive and will be updated when new props are passed in.
Setup context object that exposes properties:
attrs: Non-prop attributes (reactive)
slots: Slots object (reactive)
emit: Emit function for emitting events
expose: Function to explicitly expose public properties
Returns
The setup() function can return:
- An object of bindings to be made available to the template
- A render function (when using
h())
- Nothing (when using
<script setup>)
Example
<script>
import { ref, reactive } from 'vue'
export default {
setup(props, { emit }) {
const count = ref(0)
const state = reactive({ message: 'Hello' })
function increment() {
count.value++
emit('update', count.value)
}
return {
count,
state,
increment
}
}
}
</script>
Lifecycle
- Called before
beforeCreate hook
this is not available inside setup()
- Use Composition API functions instead (e.g.,
getCurrentInstance())
Script Setup Macros
The following compiler macros are available in <script setup>:
defineProps()
Declares component props. Can be used with runtime declaration or type-based declaration.
Type Signature:
// Runtime array syntax
function defineProps<PropNames extends string = string>(
props: PropNames[]
): Readonly<{ [key in PropNames]?: any }>
// Runtime object syntax
function defineProps<PP extends ComponentObjectPropsOptions>(
props: PP
): Readonly<ExtractPropTypes<PP>>
// Type-based declaration
function defineProps<TypeProps>(): DefineProps<
LooseRequired<TypeProps>,
BooleanKey<TypeProps>
>
Example
<script setup>
// Array syntax
const props = defineProps(['foo', 'bar'])
// Object syntax
const props = defineProps({
foo: String,
bar: {
type: Number,
required: true
}
})
// Type-based (TypeScript)
const props = defineProps<{
foo?: string
bar: number
}>()
</script>
defineEmits()
Declares component emitted events. Can be used with runtime declaration or type-based declaration.
Type Signature:
// Runtime array syntax
function defineEmits<EE extends string = string>(
emitOptions: EE[]
): EmitFn<EE[]>
// Runtime object syntax
function defineEmits<E extends EmitsOptions>(
emitOptions: E
): EmitFn<E>
// Type-based declaration
function defineEmits<T extends ComponentTypeEmits>(): ShortEmits<T>
Example
<script setup>
// Array syntax
const emit = defineEmits(['change', 'update'])
// Object syntax with validation
const emit = defineEmits({
change: null,
update: (value: number) => {
return value > 0
}
})
// Type-based (TypeScript)
const emit = defineEmits<{
change: []
update: [value: number]
}>()
emit('change')
emit('update', 1)
</script>
defineExpose()
Explicitly exposes public properties when the component is accessed by a parent via template refs.
Type Signature:
function defineExpose<Exposed extends Record<string, any>>(
exposed?: Exposed
): void
Example
<script setup>
import { ref } from 'vue'
const count = ref(0)
const increment = () => count.value++
// Only these will be accessible from parent
defineExpose({
count,
increment
})
</script>
<script setup> components are closed by default. Without defineExpose(), no properties are exposed to the parent.
defineSlots()
Provides type hints for IDE support for slot names and props. Returns the slots object.
Type Signature:
function defineSlots<S extends Record<string, any>>():
StrictUnwrapSlotsType<SlotsType<S>>
Example
<script setup lang="ts">
const slots = defineSlots<{
default(props: { msg: string }): any
header(): any
}>()
</script>
<template>
<div>
<slot name="header" />
<slot :msg="'Hello'" />
</div>
</template>
defineModel()
Declares a two-way binding prop that can be consumed via v-model from the parent component.
Type Signature:
// Default model
function defineModel<T>(
options?: PropOptions<T> & DefineModelOptions<T>
): ModelRef<T | undefined>
// Named model
function defineModel<T>(
name: string,
options?: PropOptions<T> & DefineModelOptions<T>
): ModelRef<T | undefined>
// With required/default
function defineModel<T>(
options: ({ default: any } | { required: true }) & PropOptions<T>
): ModelRef<T>
Example
<script setup>
// Default model (consumed via v-model)
const modelValue = defineModel()
modelValue.value = 'hello'
// Named model (consumed via v-model:count)
const count = defineModel('count', { default: 0 })
count.value++
// With options
const value = defineModel({ required: true, type: String })
// With get/set transformers
const modelValue = defineModel({
get: (val) => val.toUpperCase(),
set: (val) => val.toLowerCase()
})
</script>
Behavior
- If parent provides
v-model, the ref syncs with the parent prop
- If not, the ref behaves like a normal local ref
- Automatically declares the prop and corresponding
update:propName event
withDefaults()
Provides default values for type-based defineProps() declarations.
Type Signature:
function withDefaults<T, Defaults extends InferDefaults<T>>(
props: DefineProps<T, BKeys>,
defaults: Defaults
): PropsWithDefaults<T, Defaults, BKeys>
Example
<script setup lang="ts">
interface Props {
size?: number
labels?: string[]
disabled?: boolean
}
const props = withDefaults(defineProps<Props>(), {
size: 3,
labels: () => ['default label'],
disabled: false
})
</script>
- Use arrow functions
() => [] for object/array defaults
- Don’t use
() => value for primitive defaults, use the value directly