๐ŸŽจ ํ”„๋ก ํŠธ์—”๋“œ ๐ŸŒฟ ์ค‘๊ธ‰

Vue 3 Composition API

Vue 3์˜ Composition API๋กœ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์•ฑ ๋งŒ๋“ค๊ธฐ

โฑ๏ธ 8์‹œ๊ฐ„ ๐Ÿ‘๏ธ 27 ์กฐํšŒ
๐Ÿ“– ๊ฐ•์ขŒ ๋‚ด์šฉ
# Vue 3 Composition API ๊ฐ€์ด๋“œ

## ํ•™์Šต ๋ชฉํ‘œ
Vue 3์˜ Composition API๋กœ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

## 1. Vue 3๋ž€?
ํ”„๋กœ๊ทธ๋ ˆ์‹œ๋ธŒ JavaScript ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค.
- Composition API ๋„์ž…
- ๋” ๋‚˜์€ TypeScript ์ง€์›
- ํ–ฅ์ƒ๋œ ์„ฑ๋Šฅ
- ๋” ์ž‘์€ ๋ฒˆ๋“ค ํฌ๊ธฐ

## 2. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ
npm create vue@latest myapp
cd myapp
npm install
npm run dev

## 3. Composition API ๊ธฐ์ดˆ
Options API (๊ธฐ์กด):
export default {
data() {
return { count: 0 }
},
methods: {
increment() { this.count++ }
}
}

Composition API (์ƒˆ๋กœ์šด):
import { ref } from "vue"

export default {
setup() {
const count = ref(0)
const increment = () => count.value++
return { count, increment }
}
}

script setup (๊ถŒ์žฅ):
<script setup>
import { ref } from "vue"
const count = ref(0)
const increment = () => count.value++
</script>

## 4. ref์™€ reactive
ref - ๋‹จ์ผ ๊ฐ’:
const count = ref(0)
const name = ref("Kim")
console.log(count.value)
count.value++

reactive - ๊ฐ์ฒด:
const state = reactive({
name: "Kim",
age: 25
})
console.log(state.name)
state.age++

์ฐจ์ด์ :
- ref๋Š” .value ํ•„์š”
- reactive๋Š” ๊ฐ์ฒด ์ „์ฒด๋ฅผ ๋ฐ˜์‘ํ˜•์œผ๋กœ
- ref๊ฐ€ ๋” ๋ช…์‹œ์ ์ด๋ผ ๊ถŒ์žฅ

## 5. computed
import { ref, computed } from "vue"

const firstName = ref("John")
const lastName = ref("Doe")

const fullName = computed(() => {
return firstName.value + " " + lastName.value
})

์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ computed:
const fullName = computed({
get() {
return firstName.value + " " + lastName.value
},
set(newValue) {
[firstName.value, lastName.value] = newValue.split(" ")
}
})

## 6. watch์™€ watchEffect
watch - ํŠน์ • ์†Œ์Šค ๊ฐ์‹œ:
watch(count, (newVal, oldVal) => {
console.log("changed", newVal, oldVal)
})

watch(() => state.name, (newVal) => {
console.log("name changed", newVal)
})

watch([firstName, lastName], ([newFirst, newLast]) => {
console.log("changed", newFirst, newLast)
})

watchEffect - ์ž๋™ ์˜์กด์„ฑ ์ถ”์ :
watchEffect(() => {
console.log("count is", count.value)
})

## 7. ๋ผ์ดํ”„์‚ฌ์ดํด ํ›…
import { onMounted, onUnmounted, onUpdated } from "vue"

onMounted(() => {
console.log("mounted")
fetchData()
})

onUnmounted(() => {
console.log("unmounted")
cleanup()
})

onUpdated(() => {
console.log("updated")
})

## 8. Props์™€ Emit
Props ๋ฐ›๊ธฐ:
<script setup>
const props = defineProps({
title: String,
count: { type: Number, default: 0 }
})
</script>

Emit ๋ณด๋‚ด๊ธฐ:
<script setup>
const emit = defineEmits(["update", "delete"])

const handleClick = () => {
emit("update", { id: 1 })
}
</script>

## 9. provide/inject
๋ถ€๋ชจ:
import { provide } from "vue"
const theme = ref("dark")
provide("theme", theme)

์ž์‹/์†์ž:
import { inject } from "vue"
const theme = inject("theme")
const theme = inject("theme", "light") // ๊ธฐ๋ณธ๊ฐ’

## 10. Composables (์žฌ์‚ฌ์šฉ ๋กœ์ง)
composables/useFetch.js:
import { ref } from "vue"

export function useFetch(url) {
const data = ref(null)
const error = ref(null)
const loading = ref(true)

fetch(url)
.then(res => res.json())
.then(json => data.value = json)
.catch(err => error.value = err)
.finally(() => loading.value = false)

return { data, error, loading }
}

์‚ฌ์šฉ:
<script setup>
import { useFetch } from "@/composables/useFetch"
const { data, loading } = useFetch("/api/users")
</script>

## 11. Vue Router
npm install vue-router@4

import { createRouter, createWebHistory } from "vue-router"

const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/", component: Home },
{ path: "/about", component: About },
{ path: "/user/:id", component: User }
]
})

์ปดํฌ๋„ŒํŠธ์—์„œ:
import { useRouter, useRoute } from "vue-router"
const router = useRouter()
const route = useRoute()

router.push("/about")
console.log(route.params.id)

## 12. Pinia ์ƒํƒœ๊ด€๋ฆฌ
npm install pinia

stores/counter.js:
import { defineStore } from "pinia"

export const useCounterStore = defineStore("counter", {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2
},
actions: {
increment() { this.count++ }
}
})

์‚ฌ์šฉ:
<script setup>
import { useCounterStore } from "@/stores/counter"
const counter = useCounterStore()
counter.increment()
</script>

## ์ถ”์ฒœ ํ•™์Šต ์ˆœ์„œ
1. ref์™€ reactive ์ดํ•ด
2. computed์™€ watch
3. Composables ํŒจํ„ด
4. Vue Router
5. Pinia ์ƒํƒœ๊ด€๋ฆฌ