본문 바로가기
💻CODING/react. vue

[vue] vue.js 리팩토링: 공통 컴포넌트화(api 통해 뉴스 사이트 구현 ver.7)

by 코딩하는 갓디노 2021. 2. 1.

 

오픈 API를 통하여 블로그 형식의 뉴스 사이트를 
vue로 구현하는 예제(ver.7)입니다.
- 리팩토링, 공통 컴포넌트화 -



 

예제는 인프런의 캡틴 판교, "장기효"님의 Vue.js 완벽 가이드 - 실습과 리팩토링으로 배우는 실전 개념을
들으면서 공부한 내용입니다.

 

리팩토링 컴포넌트 공통화

페이지에서 사용되는 컴포넌트들의 패턴이 중복되어 사용되었을 때
이를 공통 컴포넌트화 시킴으로써 코드를 간편화, 구조화시킵니다.

구현 내용

각각의 페이지에서 사용되는 user information을 하나의 컴포넌트화 시키기 위한 작업을 합니다. 



리팩터링 작업

· components > UserProfile.vue 파일 생성
· 기존의 ItemView.vue의 내용(위 오른쪽 UI)을 copy

<template>
//기존 ItemView.vue 내용 일단 copy
  <div class="user-container">
    <div>
      <i class="fas fa-user"></i>
    </div>
    <div class="user-desc">
    //아래 부분 fetchedItem -> 사용자 정보 데이터로 바꿔줘야함(방법 2가지)
      <router-link :to="`/user/${fetchedItem.user}`">
        {{ fetchedItem.user }}
      </router-link>
      <div class="time">
        {{ fetchedItem.time_ago }}
      </div>
    </div>
  </div>
</template>

 

 

Before

views > UserView.vue

<template>
  <div>
    <div>name : {{ userInfo.id }}</div>
    <div>karma : {{ userInfo.karma }}</div>
    <div>created : {{ userInfo.created }}</div>
  </div>
</template>

 

 

after

·  UserView.vue에 UserProfile.vue import

<template>
  <div>
    <user-profile></user-profile>
  </div>
</template>

<script>
import UserProfile from "../components/UserProfile.vue";
export default {
  components: { UserProfile },
  //computed 속성 공식문서에 의해 life cycle 위에 위치
  computed: {
    userInfo() {
      return this.$store.state.user;
    },
  },

  created() {
    const userName = this.$route.params.id;
    this.$store.dispatch("FETCH_USER", userName);
  },
};
</script>

 

UserProfile에서 fetchedItem 부분에 user 정보 가지고 오는 방법 2가지
· computed에서 전달: UserView의 computed의 userInfo 객체를 그대로 가져와서 출력
· props로 전달: UserView에서 userInfo부분을 props로 전달

 

공통 컴포넌트화: 하위 컴포넌트에 computed로 데이터 전달

 

components > UserProfile.vue

<template>
  <div class="user-container">
    <div>
      <i class="fas fa-user"></i>
    </div>
    <div class="user-desc">
      <div>{{ userInfo.id }}</div> //2. userInfo로 변경
      <div class="time">
        {{ userInfo.created }} //2. userInfo로 변경
      </div>
    </div>
  </div>
</template>

<script>
export default {
  computed: { //1. UserView의 computed의 userInfo 그대로 가져옴
    userInfo() {
      return this.$store.state.user;
    },
  },
};
</script>

 

공통 컴포넌트화: 하위 컴포넌트에 props로 데이터 전달

userView.vue(상위 컴포넌트)

<template>
  <div>
    <user-profile :info="userInfo"></user-profile> //computed의 userInfo 속성을 props로 전달
  </div>
</template>

 

userProfile.vue(하위 컴포넌트)

<template>
  <div class="user-container">
    <div>
      <i class="fas fa-user"></i>
    </div>
    <div class="user-desc">
      <div>{{ info.id }}</div> //2. info로 변경
      <div class="time">
        {{ info.created }} //2. info로 변경
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: { //1. info를 props로 전달받음
    info: Object,
  },
};

 

결론

예제는 인프런의 캡틴판교, "장기효"님의 Vue.js 완벽 가이드 자료

 

vuex의 구조에 흐름에 맞는 방법은,
computed에 바로 접근하여 state로부터 데이터를 바로 가지고 오는 것이 
더 적절합니다. 



 

slot

하위 컴포넌트에서 slot을 이용하여 미완성의 틀만 만들고,
상위 컴포넌트에서 정의를 합니다. 

UserProfile.vue(하위 컴포넌트)

<template>
  <div class="user-container">
    <div>
      <i class="fas fa-user"></i>
    </div>
    <div class="user-desc">
      <slot name="username"></slot> //slot 정의
      <div class="time">
        <slot name="time"></slot>	//slot 정의
        <slot name="karma"></slot>	//slot 정의
      </div>
    </div>
  </div>
</template>

 

UserView.vue(상위 컴포넌트)

<template>
  <div>
    <user-profile :info="userInfo">
      <div slot="username">{{ userInfo.id }}</div> //slot="slot 이름" 으로 호출
      <span slot="time">{{ "Joined " + userInfo.created }}, </span> //slot 호출
      <span slot="karma">{{ userInfo.karma }}</span> //slot 호출
    </user-profile>
  </div>
</template>

 

반응형

댓글