[Vue] 컴포넌트 - Provide & Inject

youngseo·2022년 5월 2일
0
post-thumbnail

한 번에 끝내는 프론트엔드 개발 초격차 패키지 Online를 들으며 정리한 내용입니다.

Provide & Inject

1. 기본 개념

App.vue

<template>
  <Parent :msg="message" />    //Parent라는 컴포넌트에 msg라는 props부분에 message라는 데이터를 연결해서 전달
</template>
<script>
import Parent from '~/components/Parent'

export default {
  components: {
    Parent
  },
  data() {
    return {
      message: 'Hello world!'   //문자데이터 정의 (Child라는 컴포넌트에서 출력하기 위해서)
    }
  }
}
</script>

Parent.vue

<template>
  <Child :msg="msg" />   //Child라는 컴포넌트를 출력, msg라는 props부분에 msg라는 데이터를 연결해서 전달
</template>
<script>
import Child from '~/components/Child'

export default {
  components: {
    Child
  },
  props: {           //msg라는 데이터는 외부에서 받은 props옵션에 정의
    msg: {
      type: String,
      default: ''
    }
  }
}
</script>

Child.vue

<template>
  <div>
    {{ msg }}    //App.vue파일에서 정의를 해놓은 Hello world!가 msg가 되게됨.
  </div>
</template>
<script>
export default {
  porps: {
    msg: {
      type: String,
      default: '',
    }
  }
}
</script>

일반적으로 데이터를 부모에서 자식 컴포넌트로 전달해야할 때 props를 사용합니다. 현재 App.vue에 정의된 msg내용을 Child에 전달하기 위해 Parents를 거쳐가고 있습니다. Parents파일을 살펴보면 사실상 Child에게 msg내용을 전달하는 것 외에는 전혀 사용하고 있지 않음에도 데이터를 정의해 다루고 있습니다.

2. provide와 inject

이를 조금 개선하게 할 수 있지 않을까 해서 제공되는 개념이 provide와 inject라는 개념입니다. provide와 inject를 사용하면 App.vue에서 특정하게 다루는 데이터를 중간 매개체가 없더라도 Childe.vue까지 잘 전달이 되게 됩니다.
App.vue

<template>
  <Parent/>   //:msg="message"더이상 사용하지 않기에 삭제
</template>
<script>
import Parent from '~/components/Parent'

export default {
  components: {
    Parent
  },
  provide() {
    return {
      msg: this.message //data에 정의된 message를 provide의 msg라는 이름으로 사용
    }
  },
  data() {
    return {
      message: 'Hello world!'   
    }
  }
}
</script>

Parent.vue

<template>
  <Child />  //마찬가지로  :msg="msg" 삭제
</template>
<script>
import Child from '~/components/Child'

export default {
  components: {
    Child
  }                //props부분이 더이상 사용되지 않기에 삭제되었음
}
</script>

Child.vue

<template>
  <div>
    {{ msg }}  
  </div>
</template>
export default {
  inject: ['msg']  //props대신 inject작성,
  //msg가 하나의 데이터로 취급이 되어 tmeplate부분의 이중중괄호 부분으로 출력할 수 있게 됩니다.
}

3. provide와 inject 주의사항

단, provide 키워드는 기본적으로 반응성을 제공할 수 없습니다.
App.vue

<template>
  <button @click="message='Good?'">
    Click!
  </button>
  <h1>App: {{ message }}</h1>
  <Parent />
</template>

Child.vue

<template>
  <div>
    Child: {{ msg }}  
  </div>
</template>

버튼을 누르면 App파일의 내용은 잘 갱신되고 있는데, Child부분의 내용은 갱신되고 있지 않습니다.

4. 추가작업

그렇기 때문에 provide를 사용할 때는 데이터를 전달해서 출력하는 용도로만 사용하거나 혹은 반응성을 유지하기 위해 추가 작업이 필요합니다.
App.vue

import {computed} from 'vue'  

export default {
  provide() {
    return {
      msg: computed(()=> { 
        return this.message
      })
    }
  }  
}

Child.vue

<template>
  <div>
    Child: {{  msg.value }} //value속성에서 값을 얻어냄
  </div>
</template>
<script>
export default {
  inject: ['msg'] //계산된 하나의 데이터
}
</script>

vue안에서 가지고 온 computed라는 기능을 활용해서, 하나의 계산된 데이터를 만들어서 반환을 시켜 그 반환된 내용이 msg로 들어가 동작을 할 수 있게됩니다.

또한 Child 컴포넌트에는 이제 msg라는 props부분에서 넘어온 데이터는 계산된 객체데이터이기 때문에 그 객체데이터에서 원하는 내용을 출력하고 싶다면 value속성에서 그 값을 가져오면 됩니다.

조상 컴포넌트에서 자식 컴포넌트로 하나의 데이터를 넘겨줄 때는 props라는 개념을 사용할 수 있습니다. (바로 아래 자식 컴포넌트)

조상 컴포넌트에서 후손 컴포넌트로 하나의 데이터를 넘겨주려고 한다면 중간에 매개체 역할을 하는 컴포넌트가 필요합니다.

그러한 과정을 생략하기 위해서 provide라는 옵션을 통해서 데이터를 정의할 수 있습니다. (단점은 전달되는 데이터는 기존의 props와는 다르게 반응성을 가지지 않습니다. 따라서 vue라는 패키지에서 computed라는 계산된 데이터 개념을 가지고 와 그것을 동작시키는 방식으로 해당하는 데이터의 반응성을 유지한 상태로 조상요소에서 후손 컴포넌트에 데이터를 넘길 수 있습니다.)

0개의 댓글