[Vue3] Custom Event

gminnimk·2025년 3월 21일

Vue3

목록 보기
10/39

1️⃣ 왜 Custom Event가 필요한가?

  • 자식 컴포넌트부모 컴포넌트의 데이터를 직접 수정할 수 없음
    • 다른 파일에 있는 데이터이기 때문
    • props로 전달받은 데이터는 변경하면 안됨 (부작용 방지)
  • 해결책: 자식이 직접 데이터를 수정하는 대신, 부모에게 메시지(요청)를 보낸다.
    • 메시지 → "부모야, 저 데이터 좀 바꿔줘"
    • 부모는 그 메시지를 받아 데이터를 변경하는 코드를 실행

2️⃣ Custom Event 사용법 요약

자식 컴포넌트에서는:

  • $emit(이벤트명, 전달할자료) 를 사용하여 부모에게 커스텀 이벤트 전송
  • 예)
    <!-- Card.vue (자식 컴포넌트) -->
    <template>
      <div>
        <img :src="a.image" class="room-img" />
        <!-- 클릭 시 부모에게 'openModal' 이벤트를 전달 -->
        <h4 @click="$emit('openModal', a.id)"> {{ a.title }} </h4>
        <p>{{ a.price }} 원</p>
      </div>
    </template>
    
    <script setup>
    // Vue3 <script setup> 문법 사용
    // 부모로부터 'a'라는 prop 받음
    const props = defineProps({
      a: Object
    });
    // 부모에게 전달할 이벤트명 'openModal'를 명시
    const emit = defineEmits(['openModal']);
    </script>
    

부모 컴포넌트에서는:

  • 자식 컴포넌트를 사용할 때 @이벤트명 으로 이벤트 수신
  • 수신된 이벤트의 자료는 $event(또는 함수 파라미터)로 전달됨
  • 예)
    <!-- App.vue (부모 컴포넌트) -->
    <template>
      <!-- Card 컴포넌트에서 'openModal' 이벤트 수신 -->
      <Card @openModal="handleOpenModal" :a="item" />
      <!-- 모달창이 열려야 하는 조건에 따라 모달 컴포넌트 렌더링 등 -->
      <Modal v-if="modalOpen" :clickedId="clickedId" />
    </template>
    
    <script setup>
    import { ref } from 'vue';
    import Card from './Card.vue';
    import Modal from './Modal.vue';
    
    // 모달창 열림 여부와 클릭한 상품의 id를 상태로 관리
    const modalOpen = ref(false);
    const clickedId = ref(null);
    
    // 자식에서 보낸 커스텀 이벤트를 수신하여 처리하는 함수
    function handleOpenModal(payload) {
      modalOpen.value = true;  // 모달창 열기
      clickedId.value = payload;  // 전달받은 상품 id 저장
    }
    
    // 예시로 부모에서 사용할 데이터 (실제 상황에 맞게 구성)
    const item = {
      id: 0,
      image: 'https://example.com/image.jpg',
      title: '상품 제목',
      price: 10000
    };
    </script>
    

3️⃣ 핵심 정리

  • 자식이 부모의 데이터를 직접 변경할 수 없으므로, 반드시 커스텀 이벤트를 통해 '부탁'을 해야 함.
    • 자식: defineEmits(['이벤트명'])$emit('이벤트명', 자료) 사용
    • 부모: <자식컴포넌트 @이벤트명="수신시 실행할 코드" />로 처리
  • 필요 시 함수로 만들어서 처리할 수도 있음
    • (Vue2에서는 this.$emit() 사용했으나, Vue3 <script setup>에서는 위와 같이 간단히 작성 가능)

4️⃣ 추가 설명

  • 실제 사용 예: "상품 제목 누르면 모달창 열기"
    • 문제 상황: Card.vue 안의 상품 제목을 클릭하면 모달창이 열리도록 해야 하지만, 모달창 상태(모달창열렸니)는 부모(App.vue)가 가지고 있음.
    • 해결:
      • 자식(Card.vue): 클릭 시 $emit('openModal', a.id) 로 부모에게 요청
      • 부모(App.vue): <Card @openModal="handleOpenModal" />로 이벤트 수신, 받은 payload로 모달창열렸니 = true 및 클릭한 상품 id 저장
  • 커스텀 이벤트의 장점:
    • 부모와 자식 컴포넌트 간에 의존성을 낮추면서 데이터를 주고받을 수 있음
    • 컴포넌트 재사용성을 높임

0개의 댓글