[Vue.js] μ»΄ν¬λνΈ κ°λ λ° μ¬μ©λ²
1. μ»΄ν¬λνΈλ?
Vueμμ μ»΄ν¬λνΈλ UIμ μ¬μ¬μ© κ°λ₯ν λ¨μμ λλ€.
μ£Όλ‘ Vueμμ νλ©΄μ μμμ ꡬλΆνμ¬ κ°λ°νλλ° μ¬μ©ν©λλ€.
κ·ΈλΌ μ»΄ν¬λνΈλ₯Ό μ¬μ©νλ μ΄μ λ?π€·βοΈ
- μ½λμ κ°λ μ±μ λμΈλ€.
- μ μ§λ³΄μκ° μ©μ΄νλ€.
- μ½λμ μ€λ³΅μ μ€μΌ μ μλ€.
Vueμμλ κ° μ»΄ν¬λνΈλ κ³ μ μ λ°μ΄ν°, λ©μλ, ν νλ¦Ώμ κ°μ§κ³ λμν©λλ€.
νμ΄μ§μμ μ£Όλ‘ Header, Body, Footerμ κ°μ UI μμλ₯Ό μ»΄ν¬λνΈλ‘ λ§λ€κ³ ,
λ€λ₯Έ κ³³μμλ μ¬μ¬μ©ν μ μμ΄ κ΄λ¦¬κ° νΈν©λλ€.
μ»΄ν¬λνΈλ₯Ό μ€λͺ νλ©΄μ μΆκ°λ‘ λ§μλ리면,
μ΄μ κΉμ§μ Vue2μμμ μ»΄ν¬λνΈλ options APIλ₯Ό κΈ°λ°μΌλ‘ μμ±λμμ΅λλ€.
νμ§λ§ Vue3μμλ Composition APIκ° λμ λμκ³ ,
κ·Έ μ€μμλ <script setup> λ¬Έλ²μ λ μ§κ΄μ μ΄κ³ κ°κ²°ν λ°©μμΌλ‘ μ»΄ν¬λνΈλ₯Ό μμ±ν μ μλλ‘ λμμ€λλ€.
Options API μ Composition API μ νΉμ§
νΉμ§ | Options API | Composition API |
μ½λ ꡬ쑰 | μ΅μ κ°μ²΄λ‘ κΈ°λ₯μ λΆλ¦¬ (data, methods λ±) | κ΄λ ¨λ λ‘μ§μ ν κ³³μ λͺ¨μμ μ μ (ref, computed λ±) |
μ μ°μ± | κ³ μ λ ꡬ쑰, μ¬μ¬μ© μ΄λ €μ | λ‘μ§ μ¬μ¬μ© κ°λ₯, λ μ μ°ν μ½λ μμ± κ°λ₯ |
κ°λ μ± | μμ μ»΄ν¬λνΈμ μ ν© | ν° μ»΄ν¬λνΈμ μ ν©, λ‘μ§μ΄ λͺ¨λνλ¨ |
μν κ΄λ¦¬ | κ° μμ±μ΄ λλ μ Έ μμ | μνμ λ©μλκ° ν¨κ» λ¬Άμ¬ κ΄λ¦¬λ¨ |
μ»΄ν¬λνΈ κ·λͺ¨ | μμ κ·λͺ¨ μ»΄ν¬λνΈμ μ ν© | ν° κ·λͺ¨μ 볡μ‘ν μ»΄ν¬λνΈμ μ ν© |
Options API μμ
<script>
export default {
data() {
return {
count: 0
};
},
computed: {
doubleCount() {
return this.count * 2;
}
},
methods: {
increment() {
this.count++;
}
},
mounted() {
console.log('Component mounted!');
}
};
</script>
<template>
<div>
<p>{{ doubleCount }}</p>
<button @click="increment">Increment</button>
</div>
</template>
Vue2μμ μμ£Ό μ¬μ©νλ Optinos APIλ
μ£Όλ‘ data(), methods, computed, mounted λ± κ° μμ±μ κ°μ²΄λ‘ λλμ΄ μ μνλ νΉμ§μ κ°μ§κ³ μμ΅λλ€.
Composition API μμ
<script setup>
import { ref, computed, onMounted } from 'vue';
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
onMounted(() => {
console.log('Component mounted!');
});
</script>
<template>
<div>
<p>{{ doubleCount }}</p>
<button @click="increment">Increment</button>
</div>
</template>
Vue3μμ μ£Όλ‘ μ¬μ©νλ Compositions APIλ
μ£Όλ‘ ref(), computed(), onMounted() λ± Vueμ κΈ°λ₯μ ν¨μλ‘ μ¬μ©νμ¬ μμ±νλ νΉμ§μ κ°μ§κ³ μμ΅λλ€.
Vue3μμλ Composition APIλΏλ§ μλλΌ Options APIλ μ¬μ©μ΄ κ°λ₯νλ―λ‘ μν©μ λ§κ² μ μ ν μ¬μ©νμλ©΄ λ©λλ€.
2. <script setup>μ΄λ?
<script setup>μ Vue 3μμ μ 곡νλ μλ‘μ΄ λ¬Έλ²μΌλ‘, Composition APIμ λͺ¨λ κΈ°λ₯μ μ΅λν κ°λ¨νκ² μ¬μ©ν μ μλλ‘ λμμ€λλ€. κΈ°μ‘΄μ setup() ν¨μ λ΄λΆμ μμ±νλ λ‘μ§μ λ κΉλνκ² μ²λ¦¬ν μ μμΌλ©°, νΉν μ»΄ν¬λνΈλ₯Ό μμ±ν λ λ§€μ° μ μ©ν©λλ€.
<script setup>μ μ¬μ©νλ©΄ ?
- setup() ν¨μλ₯Ό μ§μ μ μνμ§ μκ³ , κ·Έ μμ λ£μ λ΄μ©μ λ°λ‘ μμ±ν μ μμ΅λλ€.
- defineProps(), defineEmits() κ°μ APIλ λ³λμ μν¬νΈ μμ΄ λ°λ‘ μ¬μ©ν μ μμ΅λλ€.
- λ κ°κ²°ν μ½λ μμ±μ΄ κ°λ₯ν©λλ€.
<script setup> μμ
<script setup>
import ChildComponent from './ChildComponent.vue'
const message = 'Hello from Parent!'
</script>
<template>
<div>
<ChildComponent :msg="message" />
</div>
</template>
3. μ»΄ν¬λνΈ μ¬μ©λ²
<script setup>μμ μ»΄ν¬λνΈλ₯Ό μ¬μ©νλ λ°©μμ λ§€μ°λ§€μ° κ°λ¨ν©λλ€.
λ€λ₯Έ μ»΄ν¬λνΈλ₯Ό κ°μ Έμ ν νλ¦Ώμμ μ¬μ©νμλ©΄ λ©λλ€.
μ»΄ν¬λνΈλ₯Ό κ°μ Έμ¬ λλ ES λͺ¨λ λ°©μμ μ¬μ©νκ³ ,
μμλ‘ μλμ κ°μ΄ μ»΄ν¬λνΈλ₯Ό μν¬νΈνκ³ ν νλ¦Ώμ μ μΈνλ©΄ λ©λλ€.
<template>
<div>
<Main></Main>
</div>
</template>
<script setup>
import Main from './views/Main.vue'
</script>
<style scoped></style>
μ μ½λλ₯Ό λΉκ΅ν΄μ μ€λͺ λ리λλ‘ νκ² μ΅λλ€.
μ°μ μ λ λ€μκ³Ό κ°μ΄ μ€μ νμμ΅λλ€.
App.vue
μ΄μ μ μμλλ©΄ μ’μ κ²μ λ¨Όμ μ€λͺ λ리μλ©΄, λμ μ€νμ μμ΄μ
첫λ²μ§Έλ‘λ main.jsμμ μμμ νκ² λ©λλ€.
Main.js
// Vue λΌμ΄λΈλ¬λ¦¬μμ createApp ν¨μ κ°μ Έμ€κΈ°
import { createApp } from 'vue'
// μν κ΄λ¦¬λ₯Ό μν΄ Pinia κ°μ Έμ€κΈ°
import { createPinia } from 'pinia'
// App.vue νμΌμμ App μ»΄ν¬λνΈ κ°μ Έμ€κΈ°
import App from './App.vue'
// λΌμ°ν° μ€μ κ°μ Έμ€κΈ°
import router from './router'
// App μ»΄ν¬λνΈλ₯Ό κΈ°λ°μΌλ‘ Vue μ ν리μΌμ΄μ
μ μμ±
const app = createApp(App)
// μν κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬μΈ Piniaλ₯Ό μ¬μ©νλλ‘ λ±λ‘
app.use(createPinia())
// Vue Routerλ₯Ό μ ν리μΌμ΄μ
μ λ±λ‘
app.use(router)
// #appμ΄λΌλ IDλ₯Ό κ°μ§ DOM μμμ μ ν리μΌμ΄μ
μ λ§μ΄νΈ
app.mount('#app')
Vueλ₯Ό λλλ§νκΈ°κΉμ§μ κ³Όμ μ μλμ κ°μ΅λλ€.
3-1. μ ν리μΌμ΄μ μμ±
- main.jsμμ createApp(App)μ νΈμΆνμ¬ Vue μ ν리μΌμ΄μ μ μμ±ν©λλ€.
- App.vueμμ μ μλ App μ»΄ν¬λνΈκ° μ ν리μΌμ΄μ μ μ΅μμ μ»΄ν¬λνΈλ‘ μ€μ λ©λλ€.
3-2. νλ¬κ·ΈμΈ λ±λ‘
- createPinia()λ₯Ό μ¬μ©ν΄ Pinia μν κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ ν리μΌμ΄μ μ λ±λ‘νμ¬κΈ, μ ν리μΌμ΄μ λ΄μμ μνλ₯Ό κ΄λ¦¬ν μ μμ΅λλ€.
- app.use(router)λ₯Ό ν΅ν΄ Vue Routerλ₯Ό λ±λ‘νμ¬ SPA(Single Page Application) κΈ°λ₯μ μΆκ°ν©λλ€.
3-3. DOMμ λ§μ΄νΈ
- app.mount('#app')λ₯Ό νΈμΆνμ¬ HTML νμΌμμ id="app"μΈ μμμ Vue μ ν리μΌμ΄μ μ λ§μ΄νΈν©λλ€. μ΄ κ³Όμ μμ Vueλ App.vueμ μ μλ λ΄μ©μ κΈ°λ°μΌλ‘ UIλ₯Ό λ λλ§ν©λλ€.
3-4. App.vue λ λλ§
- App.vueμ <template> λΆλΆμ΄ DOMμ λ λλ§λκ³ , κ·Έ μμμ μ κ° μ€μ ν <Main></Main> μ»΄ν¬λνΈκ° νΈμΆλ©λλ€.
- <script setup> λ΄μ import Main from './views/Main.vue'λ₯Ό ν΅ν΄ Main.vueλ₯Ό κ°μ Έμ€κ³ , μ΄λ₯Ό <Main> νκ·Έλ‘ μ¬μ©νμ¬ Main μ»΄ν¬λνΈλ₯Ό UIμ μΆκ°ν©λλ€.
μλ₯Ό κΈ°λ°μΌλ‘ λ€μ λμκ°μ μ€λͺ μ λ리면,
App.vueλ μ΅μμ μ»΄ν¬λνΈλ‘, μ΄κ³³μμ λ€λ₯Έ μ»΄ν¬λνΈλ₯Ό ν¬ν¨νκ±°λ λΌμ°ν°λ₯Ό μ€μ ν μ μμ΅λλ€.
μ°μ μ λ viewsλΌλ ν΄λμ Main.vueλΌλ vueνμΌμ λ§λ€κ³ λμμ μ μΈμ νμμ΅λλ€.
Main.vue
Main.vue μλ λ§μ°¬κ°μ§λ‘ Header.vue, Body.vue , Footer.vue λ₯Ό div νκ·Έ μμ μ μΈμ νμμ΅λλ€.
μ΄λ κ² λλ©΄ App.vueμμλ μ²μμ λλλ§μ΄ λ λ Main.vueλ₯Ό μΆλ ₯νκ² λλλ°,
μμ κ°μ΄ Main.vueλ Header, Body, Footer λ₯Ό μ μΈνκ³ μμΌλ―λ‘ κ°κ°μ μ»΄ν¬λνΈλ₯Ό μΆλ ₯νκ² λ©λλ€.
Header.vue
Body.vue
Footer.vue
κ²°κ΅ App.vue λ Main.vueλ₯Ό μΆλ ₯ -> Main.vueλ Header, Body, Footer μΆλ ₯ -> μ΄ 3κ°μ μ»΄ν¬λνΈ μΆλ ₯
μ κ³Όμ μ κ±°μΉκ² λ©λλ€.
κ²°κ³Όλ¬Όμ λ€μκ³Ό κ°μ΅λλ€.
μ»΄ν¬λνΈμ λν μ€λͺ λ§ νκΈ° μν΄ μμ±μ νμλλ°, μ€κ°μ€κ° νμν κ² κ°μ λΆλΆμ΄ μ μ μΆκ°λλ©΄μ
κΈμ΄ λμ‘ν΄μ§κΈ° μμνμ΅λλ€..π
νμν λΆλΆλ§ μΊμΉνμ μ 보μκΈΈ λ°λλλ€!