Vue Provide와 Inject

Bindung·2021년 7월 4일
0

vue

목록 보기
1/2
post-thumbnail

Prop로 내리는데는 한계가 있다.

Vue 프로젝트를 진행하다보면 Prop로 데이터를 자식에게 주게된다.
하지만 자식의 손자까지 아래로 계속 내려가다보면 어느 순간 한계점에 이른다.
그래서 데이터만을 쉽게 내려줄 방법이 없을까? 라는 고민이 들기 시작했다.

Provide와 Inject

vue 2.2버전 업데이트 후 새로운 것이 생겼다.
Provide와 Inject가 생겼고 이 둘은 데이터를 자신의 손자까지 마음껏 보내줄 수 있었다.

[App.vue]

<template>
  <div id="app">
    <button @click="massage = 'Good!!'">Click me!</button>
    <h1>APP: {{ massage }}</h1>
    <Parent />
  </div>
</template>

<script>
import Parent from './components/Parent.vue'
export default {
  name: 'App',
  components: {
    Parent
  },
  data() {
    return {
      massage:"Hello world"
    }
  },
  provide() {
    return { msg = this.message } //inject에게 바로 데이터를 보내준다.
  }
}
</script>

[Parent.vue]

// child에 props해주는 데이터가 없고 Child 컴포넌트만 연결
<template>
  <div id="app">
    <Child />
  </div>
</template>

<script>
import Child from './Child.vue'

export default {
  name: 'App',
  components: {
    Child
  }
}
</script>

[Child.vue]

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

<script>
export default {
  inject: ['msg'] //provide로 넘겨준 데이터 받아옴
}
</script>

정말 중간에 데이터를 쫓아가지도 않아도 된다는게 너무 기뻣다.
하지만 이것도 vue2에서는 치명적인 단점이 있었다.

Provide, Inject는 반응성이 안된다는 것이다.
부모 데이터가 변해도 Inject받은 자식은 변하지 않는다.

Javascript로 해결해보자

vue는 자바스크립트이기에 해결가능할 것 같은 예상이 들었다.
여러 삽질을 하다가 발견하였다.

Object.defineProperty()

Object.defineProperty() 정적 메서드는 객체에 직접 새로운 속성을 정의하거나 이미 존재하는 속성을 수정한 후, 그 객체를 반환합니다.
출처 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

해당 javascript를 쓰면 해결될 것 같았다.

적용

[App.vue]

<template>
  <div id="app">
    <button @click="massage = 'Good!!'">Click me!</button>
    <h1>APP: {{ massage }}</h1>
    <Parent />
  </div>
</template>

<script>
import Parent from './components/Parent.vue'
export default {
  name: 'App',
  components: {
    Parent
  },
  data() {
    return {
      massage:"Hello world"
    }
  },
  provide() {
    const msg = {}
    Object.defineProperty(msg, 'value', {
       enumerable: true,
       get: () => this.massage,
    })
    return { msg } // 객체데이터를 넘겨준다. value라는 키로...
  }
}
</script>


[Parent.vue]

// child에 props해주는 데이터가 없고 Child 컴포넌트만 연결
<template>
  <div id="app">
    <Child />
  </div>
</template>

<script>
import Child from './Child.vue'

export default {
  name: 'App',
  components: {
    Child
  }
}
</script>

[Child.vue]

<template>
  <div>
    Child: {{ msg.value }} // 넘어온 데이터의 객체데이터중 키로 받아온다.
  </div>
</template>

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

변한 것은 [App.vue], [Child.vue] 소스의 한줄뿐이다.

해결된 이미지

마무리

최근들어서 vue프로젝트를 진행하면서 데이터가 꼬이고 넘겨주고 또 넘겨주고 구조화가 잘되지 않는 소스를 만지는 사례가 많았다.
해당 내용은 v2.2부터 추가되어서 크게 인지 못했다.
좀 더 가이드문서와 친해져야겠다는 생각이 들었고 Vue3에서는 해당내용에 대해서 아주 간단하게 computed를 가져와서 간단하게 해결가능하다.

profile
포기하지말고 천천히...

0개의 댓글