Vue 프로젝트를 진행하다보면 Prop로 데이터를 자식에게 주게된다.
하지만 자식의 손자까지 아래로 계속 내려가다보면 어느 순간 한계점에 이른다.
그래서 데이터만을 쉽게 내려줄 방법이 없을까? 라는 고민이 들기 시작했다.
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받은 자식은 변하지 않는다.
vue는 자바스크립트이기에 해결가능할 것 같은 예상이 들었다.
여러 삽질을 하다가 발견하였다.
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를 가져와서 간단하게 해결가능하다.