Props
같은 경우,부모 > 자식 > 손자
컴포넌트 처럼 중첩된 컴포넌트 뎁스가 깊어질 수록 중간에props
데이터만 전달해주기 위한 코드들이 무의미하게 많이 생성된다.
Provide
와Inject
는 이와 같은 과정 없이다이렉트로
부모 컴포넌트에서 손자 컴포넌트로데이터를 전달
하는 기능이다.
Props
로 App > 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
로 App > 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
는 기본적으로반응성 주입이 안되어
있다.
추가 작업을 통해서 반응성을 주입할 수 있다.
Provide
와 Inject
는 기본적으로 반응성 주입이 안되어 있기 때문에 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
에선 반영이 안된다.
아래와 같이 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>
클릭 전
클릭 후
Provide
와 Inject
는 vue 공식 문서에도 나와 있듯이 장거리 props
라고 보면 될거 같다.
즉, 형제 컴포넌트로의 데이터 전달은 불가능하다.
형제 컴포넌트나 구조상 동떨어진 컴포넌트에 데이터를 전달하기 위해서는 emit
을 사용하거나 vuex
를 사용해야 한다.
부모, 자손 컴포넌트간에 중간 과정 없이 데이터를 쉽게 전달할 수 있는 장점이 있는 반면,
자손 컴포넌트만 보면 이 데이터가 어떤 부모 컴포넌트에서 내려왔는지 알 수 있는 방법이 없다.
프로젝트 규모가 커지면 커질수록 이런 부분은 유지보수에 어려움을 야기시킬게 뻔하다.
장단점
이 명확한Provide
와Inject
를 프로젝트 상황에 맞게 사용하는 것이 중요할듯 싶다.