본문 바로가기
Front-end/Vue.js

[Vue] options api로 웹사이트 만들기 - 4. 컴포넌트화해서 props로 데이터보내기 ( + 가상DOM )

by img 2022. 2. 23.

시작하기에 앞서, 우리가 만들고 있는 웹사이트의 완성본은 이렇게 생겼습니다! :  https://youthful-heyrovsky-6bcc71.netlify.app/ 

 

vue2-options

 

youthful-heyrovsky-6bcc71.netlify.app

코드 전체를 다 적기보다는 필요한 부분만 잘라서 설명하기때문에, 전체코드가 궁금하신 분은 : https://github.com/yoycode/vue2-options 를 참고해주세요!

 

GitHub - yoycode/vue2-options

Contribute to yoycode/vue2-options development by creating an account on GitHub.

github.com

이번 글에서는 반복되는 부분을 컴포넌트화 시키고, props

저번 글에서 v-for문으로 데이터를 뿌려준 부분인데요, (  https://imagineu.tistory.com/62 )

 

[Vue] options api로 웹사이트 만들기 - 3. v-for로 리스트 뿌려주기

저번시간에 데이터를 받아와 브라우저에 뿌려주는 것까지 봤었는데요, ( 이전 글 : https://imagineu.tistory.com/61 ) [Vue] options api로 웹사이트 만들기 - 2. axios로 API 요청하기 ( + axios 전역사용) 1. a..

imagineu.tistory.com

이 부분을 컴포넌트화 시켜서 코드를 간단하게 만들어보겠습니다. 

1. 컴포넌트 파일 생성하기

우선 /src/component 경로에 Post.vue라는 이름의 파일을 생성해주세요. 

그리고 해당 파일에서 <template> 안에, 위에서 긁어온 부분을 잘라내서 붙여내줍니다.  그러면

The template root requires exactly one element라는 에러가 뜨는데요.  지금 위의 코드를 보면 <template>안에 <img>와 <div>가 같은 최상위에 위치해있습니다.  vue 2버전에서는 다중 루트 컴포넌트가 지원되지 않기때문에, 컴포넌트의 최상위 태그를 하나로 묶어줘야합니다. 그래서 저는 <div>로 묶어주겠습니다. (vue 3버전에서는 다중 루트 컴포넌트인 fragments를 공식 지원하기때문에 최상위를 하나로 묶어줄 필요가 없습니다)

이렇게 Post.vue 컴포넌트의 최상위를 <div>로 다시 한번 묶어주었기때문에 하위노드들을 정렬시켜주는 클래스와 css를 <v-sheet>에서 긁어와주겠습니다. 

여기서, <v-sheet>를 통째로 컴포넌트화 해주면되지, 왜 굳이 불필요하게 그 아래 노드들만 긁어오고 그걸 다시 <div>로 묶었을까 하는 의문이 들 수도 있습니다. v-for문을 돌고있는 <v-sheet>를 Post.vue컴포넌트로 빼낼경우, Post.vue 컴포넌트에는 게시물 정보 "하나"가 아닌, v-for문을 돌면서 게시물을 뿌려주고 있는 게시물 목록 전체가 컴포넌트가 되게됩니다. 

vue와 같은 프론트엔드 프레임워크는, 가상DOM (virtual DOM)을 이용하고 있기 때문에, 어떤 이벤트가 일어나 DOM이 변경되어야 할 경우 전체 DOM을 다시 재렌더링해서 뿌려주는 것이 아닌 변경사항이 발생한 컴포넌트 부분만 다시 재렌더링해서 그 부분만 바꿔치게 됩니다. 그래서 하나의 컴포넌트 안에 전체 게시물 목록(여기서는 v-sheet)을 넣을 경우, 게시물 목록에서 하나의 게시물에 대해 좋아요버튼을 누른다고 가정하면, 좋아요 숫자를 +1 하느라 전체목록을 재렌더링하기때문에 불필요한 렌더링이 많아지게됩니다. 그래서 게시물 목록이 아닌 게시물 하나하나를 컴포넌트로 따로 빼준 것입니다. 

 

2. 컴포넌트 import 해주기 

컴포넌트를 만들어줬으면, 해당 컴포넌트를 부모 컴포넌트에서 불러와야겠죠. 원래 코드가 있던 App.vue 파일로 돌아와서, <script> 아래에 해당 컴포넌트를 import 해주고, components 옵션에 추가해줍니다. 

( import할 때 파일이름에 .vue를 굳이 붙이지 않아도, vue가 알아서 vue 파일로 인식해줍니다 )

그런다음 컴포넌트가 들어갈 자리에, 컴포넌트를 넣어줍니다. 컴포넌트 이름은 components 옵션에 추가한 이름과 동일하게 태그처럼 사용하면 됩니다. 

3. 부모 컴포넌트에서 자식컴포넌트로 데이터보내기 

글의 API 데이터가 나오지 않습니다. 글 목록은 부모 컴포넌트인 App.vue에서 받아온 데이터이기때문에, App.vue가 가지고 있는 데이터를 하위 컴포넌트인 Post.vue에 보내줘야 Post.vue 컴포넌트에서 해당 데이터를 받아 뿌려줄 수 있습니다. 이럴 경우 부모컴포넌트(App.vue)에서 자식컴포넌트(Post.vue)를 부르는 부분에서  :보내는이름="보내는데이터"  를 추가하면 됩니다.

우리는 이미 Post.vue의 <template>에서 item.어쩌구로 만들어놓은 코드를 그대로 긁어갔기때문에, item이라는 이름으로 item 데이터를 보내주겠습니다. 

더보기

(참고)

만약 info라는 이름으로 item데이터를 보낼경우, Post.vue에서 사용했던 item데이터는 모두 info로 바꿔줘야합니다. 

4. 자식컴포넌트에서 props 데이터받기 

Post.vue에서는 <script> 부분에서 props라는 옵션에 부모컴포넌트에서 보내준 이름을 배열형태로 작성해줍니다. 부모컴포넌트에서 여러개의 데이터를 보내더라도 배열에 각각의 이름으로 받으면 됩니다.

여기까지 해주면, 컴포넌트화가 끝났습니다!

그럼 다음글에서는 주황색 🧡 으로 뿌려주던 하트를 좋아요 수에 따라  v-if으로 조건부 렌더링해서 다르게 뿌려줘보겠습니다!

다음글 : https://imagineu.tistory.com/64

 

[Vue] options api로 웹사이트 만들기 - 5. v-if로 조건부 렌더링 (v-show 와 v-if의 차이)

저번 글에서 글 하나하나를 컴포넌트화 시켜봤었는데요. 이번 글에서는 v-if를 이용해 각 글의 좋아요 수에 따라서 하트 색상을 바꿔줘보겠습니다! 우선 글에 들어가기에 앞서, 🧡 를 어떻게 가

imagineu.tistory.com

 

 

 

 

댓글