# Composition API
## Script Setup Syntax
```vue
```
## Ref vs Reactive
```typescript
import { ref, reactive, toRefs } from 'vue'
// Use ref() for primitives
const count = ref(0)
const message = ref('hello')
const isActive = ref(true)
// Access/modify with .value
count.value++
console.log(message.value)
// Use reactive() for objects
const state = reactive({
count: 0,
user: {
name: 'John',
email: 'john@example.com'
}
})
// No .value needed for reactive
state.count++
state.user.name = 'Jane'
// Convert reactive to refs for destructuring
const { count: refCount, user } = toRefs(state)
// Now refCount.value works
```
## Computed Properties
```typescript
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
// Read-only computed
const fullName = computed(() => {
return `${firstName.value} ${lastName.value}`
})
// Writable computed
const fullNameWritable = computed({
get() {
return `${firstName.value} ${lastName.value}`
},
set(value: string) {
const [first, last] = value.split(' ')
firstName.value = first
lastName.value = last
}
})
// Computed with complex logic (cached until dependencies change)
const filteredItems = computed(() => {
return items.value.filter(item =>
item.name.toLowerCase().includes(searchQuery.value.toLowerCase())
)
})
```
## Watchers
```typescript
import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
const user = ref({ name: 'John', age: 30 })
// Watch single source
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`)
})
// Watch multiple sources
watch([count, user], ([newCount, newUser], [oldCount, oldUser]) => {
console.log('Count or user changed')
})
// Watch with options
watch(
() => user.value.name, // Getter function
(newName) => {
console.log(`Name changed to ${newName}`)
},
{
immediate: true, // Run immediately
deep: true // Deep watch for objects
}
)
// watchEffect - automatically tracks dependencies
watchEffect(() => {
console.log(`Count is ${count.value}`)
// Automatically re-runs when count changes
})
// Cleanup and stop watching
const stop = watchEffect((onCleanup) => {
const timer = setInterval(() => console.log('tick'), 1000)
onCleanup(() => {
clearInterval(timer)
})
})
// Stop watching when needed
stop()
```
## Lifecycle Hooks
```typescript
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onErrorCaptured
} from 'vue'
// Before component is mounted
onBeforeMount(() => {
console.log('Before mount')
})
// After component is mounted (DOM is ready)
onMounted(() => {
console.log('Mounted - DOM is ready')
// Fetch data, setup event listeners, etc.
})
// Before component updates
onBeforeUpdate(() => {
console.log('Before update')
})
// After component updates
onUpdated(() => {
console.log('Updated')
})
// Before component is unmounted
onBeforeUnmount(() => {
console.log('Before unmount - cleanup here')
})
// After component is unmounted
onUnmounted(() => {
console.log('Unmounted')
// Cleanup: remove event listeners, cancel timers, etc.
})
// Error handling
onErrorCaptured((err, instance, info) => {
console.error('Error captured:', err, info)
return false // Prevent error from propagating
})
```
## Composables Pattern
```typescript
// composables/useCounter.ts
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const doubled = computed(() => count.value * 2)
function increment() {
count.value++
}
function decrement() {
count.value--
}
function reset() {
count.value = initialValue
}
return {
count,
doubled,
increment,
decrement,
reset
}
}
// Usage in component
```
## Advanced Composable with Cleanup
```typescript
// composables/useEventListener.ts
import { onMounted, onUnmounted } from 'vue'
export function useEventListener(
target: EventTarget,
event: string,
handler: EventListener
) {
onMounted(() => {
target.addEventListener(event, handler)
})
onUnmounted(() => {
target.removeEventListener(event, handler)
})
}
// Usage
```
## Quick Reference
| Pattern | Use Case |
|---------|----------|
| `ref()` | Primitives (string, number, boolean) |
| `reactive()` | Objects and arrays |
| `computed()` | Derived state (cached) |
| `watch()` | Side effects on specific changes |
| `watchEffect()` | Auto-tracked side effects |
| `onMounted()` | DOM-dependent operations |
| `onUnmounted()` | Cleanup (timers, listeners) |
| Composables | Reusable stateful logic |