[Vue.js] 컴포넌트 - Provide, Inject

OROSY·2021년 5월 4일
1

Vue.js

목록 보기
25/30
post-thumbnail

컴포넌트 - Provide, Inject

컴포넌트의 provide, inject 두 개의 키워드에 대해 살펴보도록 합시다. 더욱 자세한 사항은 공식 문서를 참고해주시기 바랍니다.

1. Provide & Inject

1.1 개념

일반적으로 데이터를 부모에서 자식 컴포넌트로 전달해야할 때 props를 사용합니다. 특정한 두 컴포넌트 사이에 깊이 중첩된 컴포넌트가 있는 구조의 경우 하위 컴포넌트에서 상위 컴포넌트의 무언가가 필요한 경우를 상상해보십시오. 이 경우에 두 컴포넌트 사이의 모든 컴포넌트에 prop를 전달해야하므로 굉장히 번거로울 것입니다.

이러한 경우 provideinject 쌍을 사용할 수 있습니다. 부모 컴포넌트는 컴포넌트 계층 구조의 깊이와 상관없이 모든 자식에 대한 종속성 제공자 역할을 할 수 있습니다. 이 기능은 2개의 부분으로 구성됩니다: 부모 컴포넌트는 데이터 제공을 위해 provide 옵션을 사용하며, 자식 요소는 데이터 사용을 위해 inject 옵션을 사용합니다.

Vue의 공식 문서에 작성된 내용이며, 이에 대해서 좀 더 쉽게 알아보도록 할까요?

App.vue(조상[상위] 컴포넌트)

<Parent :msg="message" />
import Parent from '~/components/Parent'
export default {
  components: {
    Parent
  },
  data() {
    return {
      message: 'Hello world!'
    }
  }
}

Parent.vue(부모 컴포넌트)

<Child :msg="msg" />
import Child from '~/components/Child'
export default {
  components: {
    Child
  },
  props: {
    msg: {
      type: String,
      default: ''
    }
  }
}

Child.vue(자식 컴포넌트)

<div>  {{ msg }}  </div>
export default {
  props: {
    msg: {
      type: String,
      default: ''
    }
  }
}

아래의 예시처럼 손자 컴포넌트인 msg를 루트 컴포넌트에 전달하려고 하면 두 단계를 거쳐야만 하고, 중간에 있는 Parent.vue 파일의 props는 사용하지도 않지만 msg라는 데이터를 Child.vue에 전달하는 역할말고는 전혀 사용을 하고 있지 않습니다.

이러한 부분을 해결하기 위한 것이 provideinject 키워드인 것입니다.

1.2 Provide, Inject 사용 예시

App.vue(조상[상위] 컴포넌트)

<Parent />
import Parent from '~/components/Parent'
export default {
  components: {
    Parent
  },
  data() {
    return {
      message: 'Hello world!'
    }
  },
  provide() {
    return {
      msg: this.message // data()의 message 사용할게!
    }
  }
}

위처럼 data()message 옵션 부분을 providemsg라는 이름으로 사용하겠다는 코드를 작성해줍니다. 그렇다면, Parent.vue를 중간 매개체로 사용하지 않아도 되겠죠? 그러므로 html 부분에서는 <Parent /> 코드만 작성해주시면 됩니다.

Parent.vue(부모 컴포넌트)

<Child /> // :msg="msg" 부분 삭제
import Child from '~/components/Child'
export default {
  components: {
    Child
  }
}

Child.vue(자식 컴포넌트)

<div>  {{ msg }}  </div>
export default {
  inject: ['msg'] 
}

위와 같이 데이터를 받을 Child.vueinject라는 키워드를 사용하여 배열 데이터 안에 provide라는 옵션을 통해서 지정한 이름인 msg를 명시해줍니다. 그러면, msg가 하나의 데이터로 취급이 되어 {{ msg }} 이 부분에서 데이터가 출력되게 만들어줄 수 있습니다.

1.3 주의사항

이렇게 provide, inject라는 키워드를 사용하면 중간 과정 없이 바로 데이터를 전달해줄 수 있습니다. 그러나 여기서 주의사항이 있습니다.

그것은 바로 provide 키워드는 기본적으로 반응성을 제공할 수 없다는 것입니다. 그렇기 때문에 provide는 데이터를 전달해서 출력하는 용도로만 사용하거나 혹은 추가 작업이 필요합니다.

App.vue(조상[상위] 컴포넌트)

<button @click="message = 'Good?'">
  Click!
</button>
<h1>App: {{ message }}</h1>
<Parent />
import Parent from '~/components/Parent'
import { computed } from 'vue' // computed 가져오기
export default {
  components: {
    Parent
  },
  data() {
    return {
      message: 'Hello world!'
    }
  },
  provide() {
    return {
      msg: computed(() => {
        return this.message // 콜백 함수 형태로 return
      }) // msg: computed(() => this.message) // 중괄호, return 생략 가능
    }
  }
}

Child.vue(자식 컴포넌트)

<div>  {{ msg.value }}  </div> // msg라는 데이터의 value 속성 값
export default {
  inject: ['msg'] 
}

이처럼 msg라는 provide에서 넘어온 데이터는 계산된 하나의 객체 데이터이며, 그 객체 데이터에서 내가 원하는 데이터를 출력하기 위해서는 그 안의 value라는 속성을 사용해야 합니다.

이렇게 provide 키워드를 사용하여 반응성을 유지하는 데이터를 만들기 위해서는 computed라는 함수를 실행해서 그 내부에서 반응성을 갖고 싶은 데이터를 반환해주면 되는 것입니다.

profile
Life is a matter of a direction not a speed.

0개의 댓글