: (콜론) → 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를 순서대로 슬라이드 표시
'웹 개발 > Vue' 카테고리의 다른 글
| [Vue3] shallowRef (ref와의 차이) (0) | 2025.12.30 |
|---|---|
| [Vue3] Daum Post API 다음 주소를 Vue에서 사용하기 (주소) (0) | 2025.12.24 |
| [Vue3][wikibook] 4. Vue3 시작을 위한 기초 학습 (0) | 2025.08.07 |
| [Vue3] optionsAPI / compositionAPI(script setup) 비교 예제 (0) | 2025.08.07 |
| [Vue3][wikibook] 1. Vue 소개 (3) | 2025.08.06 |