HOC | high order component | Component recycling

2024. 1. 31. 14:29Study/Vue

HOC (high order component)

뷰의 하이 오더 컴포넌트는 리액트의 하이 오더 컴포넌트에서 기원된 것입니다. 리액트의 하이 오더 컴포넌트 소개 페이지를 보면 아래와 같이 정확한 정의가 나와 있습니다. A higher-order component (HOC) is an advanced technique iin React for reusing component logic. 이 말을 정리해보면 다음과 같습니다.

 

하이 오더 컴포넌트는 컴포넌트의 로직(코드)을 재사용하기 위한 고급 기술입니다.

 

 

반복되는 컴포넌트 로직

여기서 커포넌트 로직을 재사용한다는 말은 무슨 의미일까요? 이 표현에서 가리키고 있는 컴포넌트 로직이란 뷰에서 인스턴스 옵션을 의미합니다. 컴포넌트 들에서 공통적으로 들어가는 인스턴스 옵션이 있을 때 반복되는 코드를 줄여줄 수 있습니다.

 

1. high order component 정의

src/views/CreateListView.js

import EventBus from '../utils/EventBus.js'
import ListView from '../components/ListView.vue';

// high order component
export default function createListView(componentName){
  return {
    // 재사용 할 인스턴스(컴포넌트) 옵션들이 들어갈 자리
    name: componentName,
    mounted() {
      EventBus.$emit('off:loading');
      this.$store.dispatch('FETCH_LIST', this.$route.name)
        .then( () => EventBus.$emit('end:spinner')
        .catch( e => console.log(e) );
    },
    
    // render() 함수로 컴포넌트를 로딩한다.
    render(createComponent) {
      return createComponent(ListView);
    }
  }
}

 

위 코드는 CreateListComponent라는 하이 오더 컴포넌트를 구현한 코드입니다.

하이 오더 컴포넌트를 적용한 컴포넌트들의 공통 코드들(mounted, name 등)을 미리 정의합니다.

그리고 이 하이 오더 컴포넌트를 router 파일에서 사용합니다.

 

2. router에서 HOC 연결

src/router/index.js

import createListView from '../views/createListView.js';  // HOC

new VueRouter({
  routes: [
    {
      path: '/news',
      component: createListView('NewsView')
    },
    {
      path: '/ask',
      component: createListView('AskView')
    },
    // ...
  ]
})

 

위와 같은 방식으로 하이 오더 컴포넌트를 router에서 임포트 하고, 각 컴포넌트의 이름만 정의를 해주면 컴포넌트의 기본 공용 로직인 mounted(), name을 가진 컴포넌트가 생성됩니다. 따라서, 컴포넌트마다 불 필요하게 반복되는 코드를 정의 하지 않아도 됩니다.

 

src/views/ListView.vue

<template>
  <div>
    <list-item></list-item>
  </div>
</template>

<script>
import ListItem from '../components/ListItem.vue';

export default {
  components: {
    ListItem,
  }
}
</script>

 

src/components/ListItem.vue

<template>
  <ul class="item_list">
    <li v-for="(item, i) in list" :key="i" :id="item.id">

      <template v-if="item.points">
        <div class="points">
          {{ item.points }}
          <small>points</small>
        </div>
      </template>

      <div class="ttl_wrap">
        
        <strong>
          <template v-if="$route.name !== 'ask'">
            <a :href="item.url" target="blank">{{ item.title }}</a>
          </template>
          <template v-else>
            <router-link :to="`/item/${item.id}`">{{ item.title }}</router-link>
          </template>
        </strong>

        <p class="info_txt">
          <span v-if=" item.type === 'job' " class="domain"><a :href="`http://${item.domain}`" target="blank">{{ item.domain }}</a></span>
          <span v-if="item.user"><router-link :to="`/user/${item.user}`"><i class="fa-solid fa-user"></i> {{ item.user }}</router-link></span>
          <span>{{ item.time_ago }}</span>
          <span>{{ item.comments_count }} comments</span>
        </p>

      </div>

    </li>
  </ul>
</template>

<script>
import { mapGetters } from 'vuex';

export default {
  computed: {
    ...mapGetters(['list']),
  },
}
</script>

 

 

view devtools로 확인해보면 JobsView 라는 HOC가 생성된 것을 확인할 수 있다.

JobsView 컴포넌트는 HOC다

 

 

HOC (하이 오더 컴포넌트)의 단점

  • 일반: 상위 - 하위
  • HOC: 상위 - HOC - 하위

HOC를 이용하여 컴포넌트를 컴포넌트를 개발해 나가는 경우, 상위와 하위 컴포넌트 로직은 변경하지 않은 채 기능을 확장해 나갈 수 있습니다. 하지만 컴포넌트의 레벨이 깊어지고, 그로 인해 컴포넌트 간 통신이 불편해는 단점이 있습니다.

 

 


 

캡틴판교 | Cracking Vue.js | High Order Components

https://joshua1988.github.io/vue-camp/design/pattern5.html

 

High Order Components | Cracking Vue.js

컴포넌트의 코드마저 재사용하는 하이 오더 컴포넌트 정의 뷰의 하이 오더 컴포넌트는 리액트의 하이 오더 컴포넌트에서 기원된 것입니다. 리액트의 하이 오더 컴포넌트 소개 페이지 (opens new wi

joshua1988.github.io

 

 

'Study > Vue' 카테고리의 다른 글

Navigation Guard  (0) 2024.01.31
mixin | Component recycling  (0) 2024.01.31
Vuex, 헬퍼, 모듈화  (0) 2024.01.25
Composition API follower 검색기능  (0) 2023.10.04
Composition API  (0) 2023.10.04