웹 개발/Vue

[Vue3] emit, props

cha430 2025. 9. 29. 11:04

 

: (콜론) → props 전달

  • 부모 → 자식으로 값 전달
  • 동적 바인딩 시 :를 사용 (숫자, 변수, 객체 등)
  • 예시:
 
<ChildComponent :can-delete="true" :items="itemList" />
  • 위에서 can-delete와 items는 자식의 props로 전달됨

 

 


 

 

@ → 이벤트 수신

  • 자식 → 부모로 이벤트 전달 시 사용
  • 자식에서 emit한 이벤트를 부모가 듣고 처리
  • 예시:
 
<ChildComponent @deleted="onItemDeleted" />
  • 자식 컴포넌트에서:
 
const emit = defineEmits(['deleted']); emit('deleted', payload);
  • 그러면 부모 쪽 onItemDeleted 메서드가 호출됨

 


 

defineProps란?

 

  • Vue 3 Composition API에서 자식 컴포넌트가 부모로부터 받는 props를 선언하는 함수
  • 타입과 기본값 정의
  • 템플릿과 setup() 안에서 사용할 수 있게 해줌

 

const props = defineProps({
    canDelete: { type: Boolean, default: false }, // 부모에서 안 내려주면 false
    itemListRef: Object // 부모에서 내려줄 수도, 안 내려줄 수도 있음
});

 

  • 이렇게 하면 props.canDelete 또는 그냥 canDelete로 접근 가능
  • default를 지정하면 부모가 값을 안 내려줘도 기본값으로 초기화

 

 

<ImgDialog :can-delete="true" />

 

 

  • 자식에서 defineProps 선언하지 않으면
    • Vue는 props를 setup() 안에서 바로 인식 못 함
    • 그래서 setup()에서 canDelete를 쓰면 undefined
    • 템플릿에서는 여전히 동작할 수도 있지만, Composition API 내에서 안전하게 쓰기 어렵다

즉, defineProps 없으면 부모에서 반드시 바인딩해줘야 하고, 자식에서 default 값도 못 씀

 

 

 

defineProps 있으면?

  • 부모에서 바인딩 안 해도 됨 (default 있으면)
  • 부모에서 바인딩 해주면 그 값으로 덮어쓰기 됨
  • 안전하게 Composition API setup() 내에서 props를 바로 사용 가능
const canDelete = props.canDelete;

 

이런식으로 사용 가능하다는 뜻.

 

<script setup>
    const props = defineProps({
    canDelete: { type: Boolean, default: false }
});

    console.log(props.canDelete); // 항상 boolean, 부모 안 줘도 false
</script>

 


 

 

ex) ImgDialog.vue 의 삭제 버튼 출력 여부 권한

 

자식 ImgDialog 컴포넌트에서

const props = defineProps({
    canDelete: { type: Boolean, default: false },  // 부모에서 받은 삭제 가능 여부
    // itemListRef: Object
});

 

 

  • default: false라고 쓰여 있으므로
  • 부모가 :can-delete를 아예 안 내려주면 자동으로 false가 됨
  • Vue3 Composition API가 알아서 처리함.

 

<v-btn v-if="canDelete" color="red" text @click="deleteFile">이미지 삭제</v-btn>

 

  • props canDelete 값이 true면 버튼 보임, false면 숨김
  • 부모가 안 줬으면 default=false → 버튼 안 보임

❌ v-if="canDelete=true"처럼 쓰면 props 값 무시하고 무조건 true가 됨 → 의도한 것과 다를 수 있음

 

 


 

ex) ItemList.vue 의 ImgDialog 조회

 

자식 ItemList 컴포넌트에서

onClick: function (evtParam) {
    if (fileSeq) {
        emit('showImg', { fileSeq, itemName });
    }
}

 

 

  • 사용자가 시트에서 이미지 컬럼 클릭 → 이벤트 발생
  • fileSeq와 itemName만 부모에게 전달

 

 

부모 ItemUpload 컴포넌트에서

const showImg = ({ fileSeq, itemName }) => {
    if (fileSeq) {
        imgDialog.value?.open(fileSeq, itemName);
    } else {
    }
};

 

 

  • 부모는 ImgDialog 참조(ref="imgDialog")로 open() 메서드 호출
  • fileSeq 기준으로 해당 fileSeq의 모든 이미지(fileSerl 리스트)를 불러오도록 요청

 

자식 ImgDialog 컴포넌트에서

 

const open = async (fileSeq, itemName = "이미지") => {
    dialogTitle.value = itemName;
    ...
    try {
        const res = await axios.get(`../../file/getFileImages.do?fileSeq=${fileSeq}`);
        if (res.data && res.data.length) {
            images.value = res.data.map(f => ({
                fileUrl : f.fileUrl,
                fileSeq : f.fileSeq,
                fileSerl: f.fileSerl
        }));
            window.value = 0;
        } 
        ...

 

 

 

  • 서버로 GET 요청 → DB에서 fileSeq에 속한 모든 fileSerl 조회
  • 결과를 images.value 배열에 넣음
  • v-window에서 images.value를 순서대로 슬라이드 표시