๐Ÿ“— Vue.js

[Vue.js] Props์™€ Emits

JaeBBang 2024. 12. 5. 16:39

Vue.js์˜ ์ปดํฌ๋„ŒํŠธ ์‹œ์Šคํ…œ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž‘์€ ๋‹จ์œ„๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

์ด ๊ณผ์ •์—์„œ ๋ถ€๋ชจ์™€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ๊ณผ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

Vue3์˜ <script setup> ๋ฌธ๋ฒ•์„ ๊ธฐ์ค€์œผ๋กœ Props์™€ Emits์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

1. Props ( ๋ถ€๋ชจ์—์„œ ์ž์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ) ๐Ÿ‘จ ๐Ÿ‘‰ ๐Ÿ‘ฆ

Props๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ๊ฒƒ์ธ์ง€ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

1-1. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ

<template>
  <div>
    <h1>๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ</h1>
    <ChildComponent :msg="message" />
  </div>
</template>

<script setup>
import ChildComponent from './ChildComponent.vue'
const message = '์•ˆ๋…•ํ•˜์„ธ์š”. ์ €๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์™”์–ด์š”!'

</script>

 

1-2. ์ž์‹ ์ปดํฌ๋„ŒํŠธ

<template>
  <div>
    <h2>์ž์‹ ์ปดํฌ๋„ŒํŠธ</h2>
    <p>{{ msg }}</p>
  </div>
</template>

<script setup>
import { defineProps } from 'vue'
// ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์„ props๋ฅผ ์ •์˜
const props = defineProps({
  msg: {
    type: String,
    required: true,
  },
})
</script>

 

 

๊ฒฐ๊ณผ

๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌ๋˜์–ด ํ™”๋ฉด์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

 

defineProps๋Š” Vue3์˜ <script setup>๋ฌธ๋ฒ•์—์„œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์„ ์–ธํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ์˜ Props๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜ํ•˜๋ฉฐ, ์ด ์ปดํฌ๋„ŒํŠธ์—์„œ ์–ด๋–ค Props๋ฅผ ์‚ฌ์šฉํ• ์ง€ ์•Œ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ props๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„  ์œ„์™€ ๊ฐ™์ด defineProps๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ ์–ด์ฃผ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

msg  =>  props ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ :msg="message"์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜์˜€์œผ๋ฏ€๋กœ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•  ๋•Œ๋Š” msg๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

type: String  =>  props์˜ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ String์€ msg๊ฐ€ ๋ฌธ์ž์—ด์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ type์— ๋งž์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๊ฐœ๋ฐœ ์ฝ˜์†”์— ๊ฒฝ๊ณ ๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค

 

required: true  => props๊ฐ€ ํ•„์ˆ˜์ ์œผ๋กœ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ด ๊ฐ’์„ ์ „๋‹ฌํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฐœ๋ฐœ ์ฝ˜์†”์—์„œ ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

 

2. Emits ( ์ž์‹์—์„œ ๋ถ€๋ชจ๋กœ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ) ๐Ÿ‘ฆ ๐Ÿ‘‰ ๐Ÿ‘จ

Emits๋Š” ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ง์ ‘ ๋ถ€๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ , ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

 

2-1. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ

<template>
  <div>
    <h1>๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ</h1>
    <ChildComponent @custom-event="handleEvent" />
  </div>
</template>

<script setup>
import ChildComponent from './ChildComponent.vue'

const handleEvent = (data) => {
  alert(`์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ: ${data}`)
}
</script>

 

2-2. ์ž์‹ ์ปดํฌ๋„ŒํŠธ

<template>
  <div>
    <h2>์ž์‹ ์ปดํฌ๋„ŒํŠธ</h2>
    <button @click="sendEvent">์ด๋ฒคํŠธ ๋ฐœ์ƒ์‹œํ‚ค๊ธฐ</button>
  </div>
</template>

<script setup>
import { defineEmits } from 'vue'

// ๋ฐœ์ƒ์‹œํ‚ฌ ์ด๋ฒคํŠธ ์ •์˜
const emit = defineEmits(['custom-event'])

const sendEvent = () => {
  emit('custom-event', '์•ˆ๋…•ํ•˜์„ธ์š”. ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ ์™”์–ด์š”!')
}
</script>

 

 

๊ฒฐ๊ณผ

 

์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ , ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์—ฌ ์•Œ๋ฆผ์„ ๋„์›๋‹ˆ๋‹ค.

 

defineEmits๋Š” Vue3์˜ <script setup> ๋ฌธ๋ฒ•์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์— ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. emit์„ ํ†ตํ•ด ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋Š” ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

defineEmits๋ฅผ ํ†ตํ•ด ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋Š” ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ์ •์˜( ์œ„์˜ ์ฝ”๋“œ์—์„  'custom-event' )ํ•˜๊ณ , ์ด๋ฅผ emit์œผ๋กœ ๋ถ€๋ชจ์—๊ฒŒ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. emit ํ•จ์ˆ˜์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” ๋ถ€๋ชจ์—๊ฒŒ ์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ์ด๋ฉฐ ๊ฐ์ฒด, ๋ฐฐ์—ด, ๋ฌธ์ž์—ด ๋“ฑ ์–ด๋–ค ํ˜•ํƒœ๋“  ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” @์ด๋ฒคํŠธ๋ช…( ์œ„์˜ ์ฝ”๋“œ์—์„  'custom-event' ) = "ํ•จ์ˆ˜"๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ , ์ „๋‹ฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

์–ด๋А ์ฝ”๋“œ์ด๋“  ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉฐ, Props์™€ Emits๋Š” Vue์˜ ํ•ต์‹ฌ์ ์ธ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ๊ด€๋ฆฌ ๋„๊ตฌ๋กœ์จ, ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„๊ณผ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ํ†ต์‹ ์„ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ ๊ฐ„ ๊ฒฐํ•ฉ๋„๋ฅผ ์ตœ์†Œํ™” ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ์ฃผ์š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. Props๋กœ ๋ถ€๋ชจ์—์„œ ์ž์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ณ , Emits๋กœ ์ž์‹์—์„œ ๋ถ€๋ชจ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•จ์œผ๋กœ์จ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ตํ™˜ํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ, ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.