한 번에 끝내는 프론트엔드 개발 초격차 패키지 Online를 들으며 정리한 내용입니다.
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내용을 전달하는 것 외에는 전혀 사용하고 있지 않음에도 데이터를 정의해 다루고 있습니다.
이를 조금 개선하게 할 수 있지 않을까 해서 제공되는 개념이 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부분의 이중중괄호 부분으로 출력할 수 있게 됩니다.
}
단, 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부분의 내용은 갱신되고 있지 않습니다.
그렇기 때문에 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라는 계산된 데이터 개념을 가지고 와 그것을 동작시키는 방식으로 해당하는 데이터의 반응성을 유지한 상태로 조상요소에서 후손 컴포넌트에 데이터를 넘길 수 있습니다.)