Dev/Vue

Vue 데이터를 전달할 때는 props

BiCute 2022. 9. 8. 08:00
반응형

 

 

 

이제 게시물의 제목을 클릭하면 해당 게시물의 내용을 볼 수 있는 모달창을 띄워보겠습니다.

우선 각자 취향에 맞게 모달창하나 만들고 시작합시다. 지금까지의 내용을 이용하면 이제 쉽게 만들 수 있습니다.

 

 

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>

 

최종 결과

 

 

 

반응형