즐코

[vue] props로 전달할 데이터에 대하여 본문

Vue

[vue] props로 전달할 데이터에 대하여

YJLEE_KR 2022. 12. 11. 12:07

어드민 사이트의 경우 메인 진입 시 대쉬보드를 마주하는 구성이 많다.

그 대쉬보드는 여러 개의 api 요청을 통해 서버로부터 각 정보를 가져온다.

 

처음에 dashboard.vue 한 페이지 안에서 다 작성하려고 했으나, template 부분이 너무 길어져서 테이블별로 분리하기로 판단했다. (테이블이 만약 한 페이지에 5~6개 정도가 된다면, 한 컴포넌트 안에서 작성하는 것보다 테이블별로 컴포넌트를 분리하는 게 맞다고 본다)

 

그래서 아래와 같은 순서대로 작업했다.

 

1. 부모 컴포넌트 (dashboard > index.js) 안에 다수의 테이블 컴포넌트들 (dashboard > 어쩌고Table.vue)로 따로 뺐다.

2. 부모 컴포넌트에서 created() 상에서 Promise.all()로 한꺼번에 응답을 가져와서 각 테이블마다 필요한 정보들을 props로 넘겨줬다.

3. 이 때 이 가져온 정보들을 각 테이블에 뿌려줄 때, 그대로 뿌리는 게 아니라 사용자가 나름대로 보기 좋게 포맷팅해서 뿌려주는 게 맞기 때문에 각 숫자와 %를 포맷팅해주는 함수는 따로 format.js 등의 유틸함수로 빼고 각 컴포넌트마다 import해와서 썼다.

 

근데 사소하지만(?) 거슬리는 일이 발생했다!

 

새로고침을 하면 formatNum() 함수를 걸어둔 곳이 NaN으로 한 1초간 보였다가 다시 렌더되면서 원래 내가 원하던대로 포맷팅이 되서 나타나는 것이었다. 마지막엔 숫자가 이쁘게 포맷팅되서 렌더되지만, 그 중간 1초에 보이는 NaN을 참을 수 없었고 두번 렌더되는 기분이라 참을 수 없었다..

 

우선, 인스턴스 생성 순서는 부모 -> 자식 순이지만, 마운팅되는 순서는 자식 -> 부모 순이다.

이걸 눈으로 확인해보고싶다면, 부모와 자식의 created() 와 mounted() 에서 콘솔을 찍어보면 알 수 있다.

 

난 자식 created와 mounted 에서 둘다 props로 던져준 비동기 데이터를 찍어보고싶었다. 그 결과,

부모 created -> 자식 created, props: undefined -> 자식 mounted, props: undefined -> 부모 mounted 순으로 떴다.

 

- 부모 컴포넌트가 인스턴스 생성 시 서버로부터 받아오는 데이터가 비동기적인 데이터였고

- 부모 컴포넌트 인스턴스 생성 -> 자식 인스턴스 생성 -> 자식 마운트 -> 부모 마운트 순이여서

 

자식들에게 props로 넘겨준 이 데이터들이 초기엔 undefined 였기에 formatNum 함수에 넣었을 때 return 값이 NaN일 수 밖에 없었고, 그래서 첫 1초간은 NaN이 떴다가, 다시 부모 마운트 시에 props가 제대로 넘어가서 화면을 다시 렌더했기 때문에 NaN대신 원하던 포맷팅된 숫자가 뜬다고 생각된다. 

 

해결책을 찾아보니 아래 두가지 정도인 것 같다. 

 

1. 부모에서 자식으로 props를 넘겨줄 때 애초부터 다듬어서 넘겨준다. props를 따로 자식 컴포넌트에서 다듬을 필요가 없게 하란 뜻

2. 부모 컴포넌트 상에서 v-if로 전달할 props가 빈 객체가 아닐 경우에만 자식 컴포넌트를 렌더한다.

 

1번의 경우 현재 나의 상황에선 자식 컴포넌트의 template에서 format함수를 다 빼고 + 부모 컴포넌트에서 자식에게 props를 던져주기 전에 데이터를 미리 다듬는 코드를 추가해야했기에 시간을 좀 뺏을 것 같아 2번 방법을 선택하여 수정했다.

// 부모 컴포넌트 상에 아래 함수를 추가했다.
function isEmptyProps(data){
   return Object.keys(data).length === 0;
}

부모가 props로 넘겨줄 데이터가 빈 객체일 경우엔 아예 렌더를 안하게 된다.

그 후 서버로부터 데이터를 받아와 업데이트가 되면 해당 코드는 true가 되면서 렌더가 된다!

 <UserTable v-if="!isEmptyProps(gameUser)" :user="user" :gameUser="gameUser" />
 <RevenueTable v-if="!isEmptyProps(revenue)" :revenue="revenue" />

1번과 2번 중 좋은 방법이 뭔지는 아직까진 잘 모르겠다..

내가 선택한 2번은 그렇게 좋은 방법은 아닌 것 같고 애초부터 props를 다듬어서 자식들에게 던져주는 게 더 맞는 방법 같은데 이건 좀 더 알아봐야겠다! 

'Vue' 카테고리의 다른 글

json-server  (0) 2022.12.29
[vue] methods / computed / watch  (0) 2022.11.27
[vue] vue에서의 axios 요청 / axios.create() / interceptors  (1) 2022.11.26
[vue] .env 설정  (0) 2022.11.22
[vue] 라우팅  (0) 2022.11.14
Comments