μ»΄ν¬λ„ŒνŠΈμ˜ μ½”λ“œλ§ˆμ € μž¬μ‚¬μš©ν•˜λŠ” ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈ

μ •μ˜

뷰의 ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈλŠ” λ¦¬μ•‘νŠΈμ˜ ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈμ—μ„œ κΈ°μ›λœ κ²ƒμž…λ‹ˆλ‹€. λ¦¬μ•‘νŠΈμ˜ ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈ μ†Œκ°œ νŽ˜μ΄μ§€λ₯Ό 보면 μ•„λž˜μ™€ 같이 μ •ν™•ν•œ μ •μ˜κ°€ λ‚˜μ™€ μžˆμŠ΅λ‹ˆλ‹€. A higher-order component (HOC) is an advanced technique in React for reusing component logic. 이 말을 정리해보면 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈλŠ” μ»΄ν¬λ„ŒνŠΈμ˜ 둜직(μ½”λ“œ)을 μž¬μ‚¬μš©ν•˜κΈ° μœ„ν•œ κ³ κΈ‰ κΈ°μˆ μž…λ‹ˆλ‹€

λ°˜λ³΅λ˜λŠ” μ»΄ν¬λ„ŒνŠΈ 둜직

μ—¬κΈ°μ„œ μ»΄ν¬λ„ŒνŠΈμ˜ λ‘œμ§μ„ μž¬μ‚¬μš©ν•œλ‹€λŠ” 말이 무슨 μ˜λ―ΈμΌκΉŒμš”? 이 ν‘œν˜„μ—μ„œ 가리킀고 μžˆλŠ” μ»΄ν¬λ„ŒνŠΈ λ‘œμ§μ΄λž€ λ·°μ—μ„œ μΈμŠ€ν„΄μŠ€ μ˜΅μ…˜μ„ μ˜λ―Έν•©λ‹ˆλ‹€. μ½”λ“œλ‘œ λ°”λ‘œ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

<!-- ProductList.vue -->
<template>
  <section>
    <ul>
      <li v-for="product in products">
        ...
      </li>
    </ul>
  </section>
</template>

<script>
import bus from './bus.js';

export default {
  name: 'ProductList',
  mounted() {
    bus.$emit('off:loading');
  },
  // ...
}
</script>
<!-- UserList.vue -->
<template>
  <div>
    <div v-for="product in products">
      ...
    </div>
  </div>
</template>

<script>
import bus from './bus.js';

export default {
  name: 'UserList',
  mounted() {
    bus.$emit('off:loading');
  },
  // ...
}
</script>

μœ„ μ½”λ“œλŠ” ProductList λΌλŠ” μ»΄ν¬λ„ŒνŠΈμ™€ UserList μ»΄ν¬λ„ŒνŠΈμ˜ λ‘œμ§μ„ μ •μ˜ν•œ μ½”λ“œμž…λ‹ˆλ‹€. 두 μ»΄ν¬λ„ŒνŠΈκ°€ 각각 μƒν’ˆκ³Ό μ‚¬μš©μž 정보λ₯Ό μ„œλ²„μ—μ„œ 받아와 ν‘œμ‹œν•΄μ£ΌλŠ” μ»΄ν¬λ„ŒνŠΈλΌκ³  κ°€μ •ν–ˆμ„ λ•Œ, κ³΅ν†΅μ μœΌλ‘œ λ“€μ–΄κ°€λŠ” μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

name: 'μ»΄ν¬λ„ŒνŠΈ 이름',
mounted() {
  bus.$emit('off:loading');
},

name은 μ»΄ν¬λ„ŒνŠΈμ˜ 이름을 μ •μ˜ν•΄μ£ΌλŠ” 속성이고, mounted()μ—μ„œ μ‚¬μš©ν•œ 이벀트 λ²„μŠ€λŠ” μ„œλ²„μ—μ„œ 데이터λ₯Ό λ‹€ 받아왔을 λ•Œ μŠ€ν”Όλ„ˆλ‚˜ ν”„λ‘œκ·Έλ ˆμŠ€ 바와 같은 λ‘œλ”© μƒνƒœλ₯Ό μ™„λ£Œν•΄μ£ΌλŠ” μ½”λ“œμž…λ‹ˆλ‹€. 이 두 μ»΄ν¬λ„ŒνŠΈ 이외에도 μ„œλ²„μ—μ„œ 데이터 λͺ©λ‘μ„ 받아와 ν‘œμ‹œν•΄μ£ΌλŠ” μ»΄ν¬λ„ŒνŠΈκ°€ μžˆλ‹€λ©΄ 또 λΉ„μŠ·ν•œ 둜직이 반볡될 κ²ƒμž…λ‹ˆλ‹€.

이 λ•Œ 이 λ°˜λ³΅λ˜λŠ” μ½”λ“œλ₯Ό 쀄여쀄 수 μžˆλŠ” νŒ¨ν„΄μ΄ λ°”λ‘œ ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈμž…λ‹ˆλ‹€.

ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈλ‘œ 반볡 μ½”λ“œ 쀄이기

이 λ°˜λ³΅λ˜λŠ” μ½”λ“œλ₯Ό 쀄이기 μœ„ν•΄ ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈλ₯Ό κ΅¬ν˜„ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

// CreateListComponent.js
import bus from './bus.js'
import ListComponent from './ListComponent.vue';

export default function createListComponent(componentName) {
  return {
    name: componentName,
    mounted() {
      bus.$emit('off:loading');
    },
    render(h) {
      return h(ListComponent);
    }
  }
}

μœ„ μ½”λ“œλŠ” CreateListComponentλΌλŠ” ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈλ₯Ό κ΅¬ν˜„ν•œ μ½”λ“œμž…λ‹ˆλ‹€. ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈλ₯Ό μ μš©ν•  μ»΄ν¬λ„ŒνŠΈλ“€μ˜ 곡톡 μ½”λ“œλ“€(mounted, name λ“±)을 미리 μ •μ˜ν–ˆμŠ΅λ‹ˆλ‹€. 그럼 이제 이 ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈλ₯Ό μ–΄λ–»κ²Œ μ‚¬μš©ν• κΉŒμš”? μ•„λž˜λ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€.

// router.js
import createListComponent from './createListComponent.js';

new VueRouter({
  routes: [
    {
      path: 'products',
      component: createListComponent('ProductList')
    },
    {
      path: 'users',
      component: createListComponent('UserList')
    },
    ...
  ]
})

μœ„μ™€ 같은 λ°©μ‹μœΌλ‘œ ν•˜μ΄ μ˜€λ” μ»΄ν¬λ„ŒνŠΈλ₯Ό μž„ν¬νŠΈ ν•˜κ³ , 각 μ»΄ν¬λ„ŒνŠΈμ˜ μ΄λ¦„λ§Œ μ •μ˜λ₯Ό ν•΄μ£Όλ©΄ μ»΄ν¬λ„ŒνŠΈμ˜ κΈ°λ³Έ 곡용 둜직인 mounted(), nameλ₯Ό 가지고 μ»΄ν¬λ„ŒνŠΈκ°€ μƒμ„±λ©λ‹ˆλ‹€. λ”°λΌμ„œ, μ»΄ν¬λ„ŒνŠΈλ§ˆλ‹€ 뢈 ν•„μš”ν•˜κ²Œ λ°˜λ³΅λ˜λŠ” μ½”λ“œλ₯Ό μ •μ˜ν•˜μ§€ μ•Šμ•„λ„ λ©λ‹ˆλ‹€.