Provide, Inject

jude·2022년 2월 15일
0

vue

목록 보기
9/14
post-thumbnail

Provide와 Inject

Props 같은 경우, 부모 > 자식 > 손자 컴포넌트 처럼 중첩된 컴포넌트 뎁스가 깊어질 수록 중간에 props 데이터만 전달해주기 위한 코드들이 무의미하게 많이 생성된다.
ProvideInject는 이와 같은 과정 없이 다이렉트로 부모 컴포넌트에서 손자 컴포넌트로 데이터를 전달하는 기능이다.

중첩 컴포넌트의 Props 데이터 전달

PropsApp > Parent > Child 데이터 전달하기

<!-- App.vue -->
<template>
  <h1>App</h1>
  <Parent :msg="msg" />
</template>

<script>
import Parent from '~/components/Parent'

export default {
  components: {
    Parent
  },
  data() {
    return {
      msg: 'Hello jude'
    }
  }
}
</script>
<!-- Parent.vue -->
<template>
  <Child :msg="msg" />
</template>

<script>
import Child from '~/components/Child'

export default {
  components: {
    Child
  },
  props: {
    msg: {
      type: String,
      default: ''
    }
  }
}
</script>
<!-- Child.vue -->
<template>
  <div>Child : {{ msg }}</div>
</template>

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

렌더된 화면

중첩 컴포넌트의 Provide, Inject 데이터 전달

Provide, InjectApp > Parent > Child 데이터 전달하기

<!-- App.vue -->
<template>
  <h1>App</h1>
  <Parent />
</template>

<script>
import Parent from '~/components/Parent'

export default {
  components: {
    Parent
  },
  data() {
    return {
      msg: 'Hello jude'
    }
  },
  provide() {
    return {
      message: this.msg
    }
  }
}
</script>
<!-- Parent.vue -->
<template>
  <Child />
</template>

<script>
import Child from '~/components/Child'

export default {
  components: {
    Child
  }
}
</script>
<!-- Child.vue -->
<template>
  <div>Child : {{ message }}</div>
</template>

<script>
export default {
  inject: ['message']
}
</script>

렌더된 화면

Provide와 Inject 주의사항

ProvideInject는 기본적으로 반응성 주입이 안되어 있다.
추가 작업을 통해서 반응성을 주입할 수 있다.

ProvideInject는 기본적으로 반응성 주입이 안되어 있기 때문에 App.vue에서 데이터를 변경해도, Child.vue에선 변경된 데이터 반영이 안된다.

<!-- App.vue -->
<template>
  <h1>App</h1>
  <button type="button" @click="msg = 'change?'">Click</button>
  <Parent />
</template>

App.vue의 버튼 클릭을 해서 msg 데이터를 변경해도 Child.vue에선 반영이 안된다.

Provide와 Inject에 반응성 주입하기

아래와 같이 vue 인스턴스의 computed() 메서드를 가져와 사용하면 반응성이 주입된다.

<!-- App.vue -->
<script>
import Parent from '~/components/Parent'
import { computed } from 'vue' // computed 메서드 가져오기

export default {
  components: {
    Parent
  },
  data() {
    return {
      msg: 'Hello jude'
    }
  },
  provide() {
    return {
      message: computed(() => this.msg)
    }
  }
}
</script>

그리고 데이터를 받는 Child 부분에선 message 데이터가 이젠 객체로 넘어오기 때문에 message.value를 작성하여 원래 데이터를 출력시킬 수 있다.

<!-- Child.vue -->
<template>
  <div>Child : {{ message.value }}</div>
</template>

<script>
export default {
  inject: ['message']
}
</script>

클릭 전

클릭 후

결론

ProvideInject는 vue 공식 문서에도 나와 있듯이 장거리 props라고 보면 될거 같다.

즉, 형제 컴포넌트로의 데이터 전달은 불가능하다.
형제 컴포넌트나 구조상 동떨어진 컴포넌트에 데이터를 전달하기 위해서는 emit을 사용하거나 vuex를 사용해야 한다.

부모, 자손 컴포넌트간에 중간 과정 없이 데이터를 쉽게 전달할 수 있는 장점이 있는 반면,
자손 컴포넌트만 보면 이 데이터가 어떤 부모 컴포넌트에서 내려왔는지 알 수 있는 방법이 없다.
프로젝트 규모가 커지면 커질수록 이런 부분은 유지보수에 어려움을 야기시킬게 뻔하다.

장단점이 명확한 ProvideInject를 프로젝트 상황에 맞게 사용하는 것이 중요할듯 싶다.

profile
UI 화면 만드는걸 좋아하는 UI개발자입니다. 프론트엔드 개발 공부 중입니다. 공부한 부분을 블로그로 간략히 정리하는 편입니다.

0개의 댓글