vue3 emit 사용법

developer.do·2023년 9월 22일
0

자꾸 헷갈리는 emit 사용법을 한 번 정리해보자

상황

기본모달 - 닫기, 열기 버튼이 Modal 공용 컴포넌트에 있는 경우
Footer가 있는 모달 - 닫기 버튼이 Modal을 실행하는 컴포넌트 밖에 있는 경우

MODAL공용컴포넌트.vue

<script setup lang="ts">
import type { IModalProps } from '~/types/modal'
import { MODAL_SIZE } from '~/types/modal'

const props = withDefaults(defineProps<IModalProps>(), {
  title: '',
  size: '',
  closeOnClickModal: true,
  confirmText: '확인',
  cancelText: '취소',
})
const emit = defineEmits<{
  (e: 'update:modelValue', modelValue: boolean): void
  (e: 'cancel'): void
  (e: 'confirm'): void
}>()

const modalShow = computed({
  get() {
    return props.modelValue
  },
  set(value) {
    emit('update:modelValue', value)
  },
})
 

const cancel = () => {
  emit('cancel')
}

const confirm = () => {
  emit('confirm')
}
</script>

<template>
  <div>
    <el-dialog
      v-model="modalShow"
      :width="calculateModalWidth"
      align-center
      :before-close="cancel"
      :close-on-click-modal="closeOnClickModal"
      destroy-on-close
    >
      <template v-if="title.length" #header>
        <span class="modal__title"> {{ title }} </span>
      </template>
      <slot name="content" />
      <template #footer>
        <slot name="footer">
          <button type="button" class="btn__primary-line btn--lg" @click="cancel">  // 여기는 기본 modal 컴포넌트의 닫기 버튼임
            // click 함수를 실행하면 cancel이라는 인자값을 전달함
            {{ props.cancelText }}
          </button>
          <button type="button" class="btn__search" @click="confirm">
            {{ props.confirmText }}
          </button>
        </slot>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped></style>


모달을 사용하는 상위컴포넌트

<script setup lang="ts">
 
const titleName = ref<string>('모달제목')

const popup: IModalPopup = reactive({
  modalShow: {
    show: false,
  },
  modalShowFooter: {
    show: false,
  },
})



const openModal = (modal: string) => {
  popup[modal].show = true
}


// 여기있는 함수를 이용해서, 자식에서 보낸 emit을 받는다.
const handleCancel = (modal: string) => {
  popup[modal].show = false
}
const handleConfirm = (modal: string) => {
  popup[modal].show = false
}
</script>

<template>
  <div>
    <!-- 기본 모달(Footer가 없을 때) -->
    <p>
      기본 모달
      <el-button @click="openModal('modalShow')">
        모달 클릭
      </el-button>
    </p>
    <Modal v-model="popup.modalShow.show" :title="titleName" :size="MODAL_SIZE.LARGE" @confirm="handleConfirm('modalShow')" @cancel="handleCancel('modalShow')">
      // @cancel = 자식에서 emit으로 보낸 함수
      // handleCancel = 자식에서 emit으로 보낸 함수를 실행하는 함수
      // ('modalShow') = 인자값으러 넘기기
      <template #content>
        <p>모달 내용</p>
      </template>
    </Modal>

    <!-- Footer가 있는 모달 -->
    <p>
      Footer가 있는 모달
      <el-button @click="openModal('modalShowFooter')">
        모달 클릭
      </el-button>
    </p>

    <Modal v-model="popup.modalShowFooter.show" :title="titleName" :close-on-click-modal="false">
      <template #content>
        <p>모달 내용 </p>
      </template>
      <template #footer>
        <button class="btn__primary-line btn--lg" @click="handleCancel('modalShowFooter')">
          취소(Footer)
        </button>
        <button class="btn__search" @click="handleConfirm('modalShowFooter')">
          확인(Footer)
        </button>
      </template>
    </Modal>
  </div>
</template>

<style scoped></style>


0개의 댓글