이제 게시물의 제목을 클릭하면 해당 게시물의 내용을 볼 수 있는 모달창을 띄워보겠습니다.
우선 각자 취향에 맞게 모달창하나 만들고 시작합시다. 지금까지의 내용을 이용하면 이제 쉽게 만들 수 있습니다.
1. 모달창 만드는 방법
(1) 처음부터 뭔가 눌렀을때, 어떻게 해야 모달창이 나타나는것인지 어렵게 생각하지말고 최종적으로 나와있을때의 모습을 기준으로 구현하세요.
(2) 그리고 그 창을 끄고 켤수 있는 버튼 (v-if)만 만들어주면 모달창 완성입니다.
(이런 방식은 모달창 뿐만 아니라 애니메이션 효과도 동일합니다)
저는 아래와 같이 대충 만들어 봤습니다 (스타일은 코드가 너무 길어지니 생략)
// ModalPopup.vue
<template>
<div class="popup">
<h2 class="popupTitle">제목</h2>
<p class="popupDate">작성일</p>
<p class="popupContents">내용</p>
<button class="closeButton">닫기</button>
</div>
</template>
<script>
export default {
name:"ModalPopup",
}
</script>
아래는 현재 app.vue의 전체적인 내용입니다.
// app.vue
<template>
<MainHeader />
<div v-for="(item, index) in post" :key="index" class="blogPost">
<p>제목: {{ item.title }}</p>
<p>작성일: {{ item.date }}</p>
</div>
<ModalPopup v-if="ModalPopup" /> // <-- 모달 컴포넌트
</template>
<script>
import MainHeader from './components/MainHeader.vue'
import ModalPopup from './components/ModalPopup.vue' // <-- import
export default {
name: 'App',
components: {
MainHeader,
ModalPopup, // <-- 컴포넌트 등록
},
data() {
return {
ModalPopup: false, // <-- 모달창을 열고닫기위한 데이터
post: [
{
title: "게시물 제목 1",
contents: "게시물 내용 1",
date: "2022.02.08"
},
{
title: "게시물 제목 2",
contents: "게시물 내용 2",
date: "2022.02.16"
},
{
title: "게시물 제목 3",
contents: "게시물 내용 3",
date: "2022.08.26"
}
],
}
},
}
</script>
이제 모달창 구현은 끝났습니다.
ModalPopup 데이터값만 true, false로 바꿔주면 아래와 같이 팝업창이 열리고 닫히게 됩니다.
데이터값을 true, false로 바꾸는 방법은?
Vue 이밴트 핸들링(v-on)에서 사용했던 클릭 이벤트를 이용하여 해당 요소를 클릭하면 ModalPopup의 값을 true로 바꿔돌라고 부탁하면 됩니다.
처음 계획대로 제목을 클릭하면 창이 열리게 해 봅시다.
// App.vue
<p @click="ModalPopup = true">제목: {{ item.title }}</p>
2. props - 부모의 데이터를 자식에게 전달하기
자, 이제 모달창은 열수 있게 되었으니 게시물에 따른 데이터를 출력하도록 바꿔 봅니다.
(창을 닫는 과정은 이 이후에)
모달창에서 기존에 하던 방식으로 아래와 같이 데이터 바인딩을 해도 적용이 되질 않습니다.
<h2>제목: {{ post[0].title }}</h2>
<p>작성일: {{ post[0].date }}</p>
<p>내용: {{ post[0].contents }}</p>
이유는 post라는 데이터는 부모요소인 app.vue에 있고 자식요소인 모달창에는 해당 데이터값이 없기 때문입니다.
그렇기 때문에 부모에게서 그 데이터를 받아와야 하는데 이렇게 부모요소가 자식요소에게 데이터를 전달해 줄 때 props를 사용하게 됩니다.
props를 등록하고 사용하는 방법
props를 등록하고 사용하는 방법은 3단계로 나뉩니다.
(1) 전달해주고 싶은 컴포넌트에서 v-bind 형식으로 다음과 같이 전달합니다.
아래 내용은 ModalPopup 이라는 컴포넌트에 post라는 이름으로 "post"데이터 값을 보낸다는 의미입니다.
<ModalPopup :post="post" />
(2) 자식요소에서 가져온 프롭스를 등록해 줍니다.
props라는 항목을 만들고 props로 전달받은 데이터와 해당 데이터의 타입을 작성해 줍니다.
위에서 가져온 post는 배열 형식이기에 Array로 등록해 줍니다.
<script>
export default {
name:"ModalPopup",
props: {
post: Array, // <-- 가져온 요소의 타입(Number, Array, Object 등) 지정
}
}
</script>
(3) 가져온 요소 사용하기.
이제 원하는 곳에 데이터 바인딩을 해보면 해당 내용이 배열 형식으로 출력되는것을 확인할 수 있습니다.
{{ post }}
이제 모달창의 post값에서 배열의 index값만 바꿔주면 정상적으로 원하는 데이터가 출력이 될것인데...
index값을 변경하기 위해선 부모 요소에서 index값도 함께 가져와야 합니다.
index값도 가져와보자
위 과정과 동일하니 짧게 생략하면,
(1) 부모 요소인 App.vue에서 인덱스값을 담을 변수를 하나 더 만듭니다.
data() {
return {
selectPost: 0, // <-- index 번호를 담을 변수 추가
}
}
(2) 해당 반복문에서 index번호를 알아낼 방법을 찾아야 하는데, 반복문에는 항상 순번값을 돌려주는 index 값이 이곳에 이미 지정되어 있습니다.
해당 버튼을 클릭했을때 위에서 지정한 selectPost값을 index 번호로 바뀌도록 하여 넘겨주면 될거 같습니다.
<div v-for="(item, index) in post" :key="index" class="blogPost">
<p @click="ModalPopup = true, selectPost = index">제목: {{ item.title }}</p>
<p>작성일: {{ item.date }}</p>
</div>
(3) 위에서 selectPost값이 바뀌도록 설정하였으니 이 값도 함께 자식 요소에게 props로 전달합니다.
<ModalPopup :post="post" :selectPost="selectPost" v-if="ModalPopup" />
(4) 자식 요소는 전달받은 프롭스 값을 등록하고
props: {
post: Array,
selectPost: Number, // <-- 이번엔 그냥 숫자값만 가지고 있으니 Number
}
(5) 이제 HTML영역에 데이터 바인딩을 하면 완료입니다.
<template>
<div class="popup">
<h2 class="popupTitle">제목: {{ post[selectPost].title }}</h2>
<p class="popupDate">작성일: {{ post[selectPost].date }}</p>
<p class="popupContents">내용: {{ post[selectPost].contents }}</p>
<button class="closeButton">닫기</button>
</div>
</template>
최종 결과