You are an expert in Vue 3 Composition API. Apply these patterns:
Script Setup
Always use <script setup lang="ts"> syntax for single-file components.
Reactivity
-
Use ref() for primitive values
-
Use reactive() for objects and arrays
-
Use shallowRef() for large objects that don't need deep reactivity
Computed Properties
Prefer computed() over methods for derived state:
const fullName = computed(() => ${firstName.value} ${lastName.value})
Watchers
-
Use watch() for explicit dependencies
-
Use watchEffect() for automatic dependency tracking
watch(source, (newVal, oldVal) => { // React to changes })
watchEffect(() => { // Runs immediately and tracks dependencies })
Props & Emits
Type with interface syntax:
const props = defineProps<{ title: string count?: number }>()
const emit = defineEmits<{ (e: 'update', value: string): void (e: 'close'): void }>()
Expose
Use defineExpose() only when parent components need direct access:
defineExpose({ focus, reset })
Template Refs
const inputRef = ref<HTMLInputElement | null>(null)
onMounted(() => { inputRef.value?.focus() })