144 lines
4.0 KiB
Markdown
144 lines
4.0 KiB
Markdown
---
|
||
id: wiki-20260508-composition-api-redir
|
||
title: Composition API
|
||
category: 10_Wiki/Topics
|
||
status: verified
|
||
canonical_id: self
|
||
aliases: [Vue Composition API, setup()]
|
||
duplicate_of: none
|
||
source_trust_level: A
|
||
confidence_score: 0.95
|
||
verification_status: applied
|
||
tags: [vue, reactivity, frontend]
|
||
raw_sources: []
|
||
last_reinforced: 2026-05-10
|
||
github_commit: pending
|
||
tech_stack:
|
||
language: TypeScript
|
||
framework: Vue 3
|
||
---
|
||
|
||
# Composition API
|
||
|
||
## 매 한 줄
|
||
> **"매 logic-by-feature, not-by-option"**. 매 Vue 2 의 Options API (data/computed/methods 의 monolithic blob) 의 limitation 매 large component 의 reuse 의 difficulty → 매 Vue 3 (2020) 의 setup-function-based, ref/reactive primitive, custom-composables 의 pattern.
|
||
|
||
## 매 핵심
|
||
|
||
### 매 primitives
|
||
- `ref<T>(initial)` — 매 single value reactive container, `.value` access.
|
||
- `reactive<T>(obj)` — 매 deep proxy 의 object.
|
||
- `computed(() => ...)` — 매 lazy + cached derived.
|
||
- `watch(source, cb)` — 매 reactive side-effect.
|
||
- `watchEffect(cb)` — 매 auto-track dependencies.
|
||
|
||
### 매 modern (Vue 3.4+ / 2026)
|
||
- `<script setup>` SFC syntax (default in Vue 3.2+).
|
||
- `defineProps`, `defineEmits`, `defineExpose`, `defineModel` (3.4).
|
||
- Reactivity Transform 매 deprecated → 매 macros 의 explicit `.value`.
|
||
|
||
### 매 응용
|
||
1. Custom composables (replace mixins).
|
||
2. Cross-component state via VueUse / Pinia.
|
||
3. Type-safe props/emits via `defineProps<T>()`.
|
||
|
||
## 💻 패턴
|
||
|
||
### `<script setup>` baseline
|
||
```vue
|
||
<script setup lang="ts">
|
||
import { ref, computed } from 'vue';
|
||
const count = ref(0);
|
||
const double = computed(() => count.value * 2);
|
||
const inc = () => count.value++;
|
||
</script>
|
||
|
||
<template>
|
||
<button @click="inc">{{ count }} (×2 = {{ double }})</button>
|
||
</template>
|
||
```
|
||
|
||
### Custom composable
|
||
```ts
|
||
// useCounter.ts
|
||
import { ref, computed } from 'vue';
|
||
|
||
export function useCounter(initial = 0, step = 1) {
|
||
const count = ref(initial);
|
||
const double = computed(() => count.value * 2);
|
||
const inc = () => (count.value += step);
|
||
const reset = () => (count.value = initial);
|
||
return { count, double, inc, reset };
|
||
}
|
||
```
|
||
|
||
### Async data with `useFetch` (VueUse)
|
||
```ts
|
||
import { useFetch } from '@vueuse/core';
|
||
const { data, error, isFetching } = useFetch<User[]>('/api/users').json();
|
||
```
|
||
|
||
### `defineModel` (Vue 3.4)
|
||
```vue
|
||
<script setup lang="ts">
|
||
const model = defineModel<string>({ required: true });
|
||
</script>
|
||
<template>
|
||
<input v-model="model" />
|
||
</template>
|
||
```
|
||
|
||
### `watch` + `watchEffect`
|
||
```ts
|
||
import { watch, watchEffect } from 'vue';
|
||
watch(count, (v, old) => console.log('count', old, '→', v));
|
||
watchEffect(() => console.log('auto-tracks', count.value));
|
||
```
|
||
|
||
### Provide/Inject typed
|
||
```ts
|
||
// parent
|
||
import { provide } from 'vue';
|
||
import type { InjectionKey } from 'vue';
|
||
const ThemeKey: InjectionKey<Ref<'light' | 'dark'>> = Symbol();
|
||
provide(ThemeKey, theme);
|
||
|
||
// child
|
||
import { inject } from 'vue';
|
||
const theme = inject(ThemeKey, ref('light'));
|
||
```
|
||
|
||
## 매 결정 기준
|
||
| 상황 | API |
|
||
|---|---|
|
||
| Vue 2 legacy | Options API |
|
||
| Vue 3 new code | Composition API + `<script setup>` |
|
||
| Cross-component state | Pinia (composition-style) |
|
||
|
||
**기본값**: `<script setup>` + composables + Pinia.
|
||
|
||
## 🔗 Graph
|
||
- 부모: [[Vue]]
|
||
- 변형: [[Options-API]] · [[Reactivity-Transform]]
|
||
- 응용: [[VueUse]] · [[Pinia]]
|
||
- Adjacent: [[React-Hooks]] · [[Solid-Signals]]
|
||
|
||
## 🤖 LLM 활용
|
||
**언제**: Vue 3+ component logic, reusable stateful logic, TS-first SFCs.
|
||
**언제 X**: Vue 2 codebase 매 still on Options API; team unfamiliar with reactivity primitives.
|
||
|
||
## ❌ 안티패턴
|
||
- **Forgetting `.value` on refs**: 매 silently broken reactivity.
|
||
- **Destructuring `reactive()` 의 result**: 매 loses reactivity (use `toRefs`).
|
||
- **Mega-`setup()`**: 매 extract composables.
|
||
|
||
## 🧪 검증 / 중복
|
||
- Verified (vuejs.org/api/composition-api-setup.html, Vue 3.4 release notes).
|
||
- 신뢰도 A.
|
||
|
||
## 🕓 Changelog
|
||
| 날짜 | 변경 |
|
||
|---|---|
|
||
| 2026-05-08 | Phase 1 |
|
||
| 2026-05-10 | Manual cleanup — Composition API FULL Vue 3.4+ patterns |
|