안녕하세요.
이번에는 Vue 를 사용하면서 저를 많이 혼란스럽게 했던 기능 중 주요 기능인
상위, 하위 컴포넌트간 데이터 전달 방법에 대해 살펴보려고 합니다.
오늘도 미래의 저에게 도움이 될수 있기를!
요 근래 Vue 를 공부하는 중 상위, 하위 컴포넌트간 데이터 통신이 자주 필요했습니다.
주고 받을수 있는 방법은 정리해보자면 다음과 같았습니다.
this.$root
혹은this.$parent
를 이용v-bind
와props
,v-on
이벤트와$emit
를 이용v-model
를 이용- EventBus 를 이용
- vuex 의 store 공통객체를 이용
전부 다 Vue에서 데이터를 전달하고 관리하기 용의한 방법들입니다. (이렇게나 많네요!)
여기서 vuex 를 이용하는 방법은 글로벌한 공통 상태값을 관리하기에 적합하나
한정된 컴포넌트간의 통신에는 부적합하여 패스.
EventBus 로 가능하지만 자주 사용하게 되면 나중에 이벤트를 추적 관리하기 힘들어지기 때문에 패스!
남은 방법들을 검토했습니다.
# App.vue
<template>
<div id="app">
<child></child>
</div>
</template>
<script>
import Child from '@/components/Child.vue'
export default {
name: 'App',
data: function () {
return {
rootData: 10
}
},
components: {
// Child 컴포넌트를 하위 컴포넌트로 등록
'child': Child
}
}
</script>
<style>
...
</style>
# Child.vue
<template>
<div>
Child
<child-child></child-child>
</div>
</template>
<script>
import ChildAndChild from '@/components/ChildAndChild.vue'
export default {
name: 'Child',
data: function () {
return {
childData: 20
}
},
components: {
// Child 컴포넌트를 하위 컴포넌트로 등록
'child-child': ChildAndChild
}
}
</script>
# ChildAndChild.vue
<template>
<div>
Child And Child
<button @click="showRootLog">Root 데이터 조회</button>
<button @click="showParentLog">Parent 데이터 조회</button>
</div>
</template>
<script>
export default {
name: 'ChildAndChild',
methods: {
showRootLog: function () {
},
showParentLog: function () {
}
}
}
</script>
this.$root 와 this.$parent
3개의 예제에서 ChildAndChild.vue
에 다음과 같이 작성해봅시다.
<template>
<div>
Child And Child
<button @click="showRootLog">Root 데이터 조회</button>
<button @click="showParentLog">Parent 데이터 조회</button>
</div>
</template>
<script>
export default {
name: 'ChildAndChild',
methods: {
showRootLog: function () {
console.log('rootData', this.$root.rootData)
},
showParentLog: function () {
console.log('childData', this.$parent.childData)
}
}
}
</script>
그러면 App.vue
와 Child.vue
에 정의된 데이터가 콘솔창에 조회 될 것 입니다.
이런식으로 조회도 가능하지만 수정도 가능하기 때문에 제일 간단하게 사용할수 있는 장점도 있으나 단점도 있습니다.
앞서 말한 EventBus 와 동일한 이유인데요.
프로젝트가 작고 상관없으나 프로젝트가 커지게 되면 이를 이용한 수정을 했을때 이벤트 추적이 힘들어질수 있을수 있습니다.
그래서 개인적으로 권장하고 싶지는 않지만 가장 단순하게 컴포넌트간 데이터를 활용할수 있는 방법입니다.
v-bind 와 props, v-on 이벤트와 $emit 을 이용
# Child.vue
<template>
<div>
Child
<child-child :send-data="childData" @event-data="setChildData"></child-child>
</div>
</template>
<script>
import ChildAndChild from '@/components/ChildAndChild.vue'
export default {
name: 'Child',
data: function () {
return {
childData: 20
}
},
components: {
// Child 컴포넌트를 하위 컴포넌트로 등록
'child-child': ChildAndChild
},
mehtods: {
setChildData (data) {
this.childData = data
console.log(this.childData)
}
}
}
</script>
# ChildAndChild.vue
<template>
<div>
Child And Child
<button @click="showParentLog">Parent 데이터 조회</button>
<button @click="sendEditData">Parent 데이터 수정</button>
</div>
</template>
<script>
export default {
name: 'ChildAndChild',
props: ['sendData']
methods: {
showParentLog: function () {
console.log('child 데이터', this.sendData)
},
sendEditData: function () {
console.log('child 데이터 수정 후 전달')
let changeData = this.sendData + 30
this.$emit('event-data', changeData)
}
}
}
</script>
두 묶음(?) 방법의 활용도는 다음과 같습니다.
- v-bind + props : 상위 컴포넌트에서 하위 컴포넌트로의 데이터 전달
- v-on + $emit : 하위 컴포넌트에서 상위 컴포넌트로 데이터 전달
두가지를 동시에 사용하게 되면 이런 시나리오도 가능하게 됩니다.
- 하위 컴포넌트로 데이터를 전달한다.
- 하위 컴포넌트에서 전달 받은 데이터를 이용하여 가공을 한다.
- 가공된 데이터를 상위 컴포넌트에 전달하여 갱신한다.
간단하게 조회와 수정, 갱신이 가능하게 되는 거죠.
이 방법을 사용하게 되면 인과 관계가 명확하게 되므로 프로젝트가 커지더라도 이벤트의 추적이 용의하게 됩니다.
그런데 이 방법을 하나의 속성을 이용하여 최적화가 가능한 방법이 있습니다.
v-model 를 이용
이전 예제 코드를 다음과 같이 수정합니다.
# Child.vue
<template>
<div>
Child
<child-child v-model="childData"></child-child>
<button @click="showDataLog">데이터 조회</button>
</div>
</template>
<script>
import ChildAndChild from '@/components/ChildAndChild.vue'
export default {
name: 'Child',
data: function () {
return {
childData: 20
}
},
components: {
// Child 컴포넌트를 하위 컴포넌트로 등록
'child-child': ChildAndChild
},
mehtods: {
showDataLog () {
console.log(this.childData)
}
}
}
</script>
# ChildAndChild.vue
<template>
<div>
Child And Child
<button @click="showParentLog">Parent 데이터 조회</button>
<button @click="sendEditData">Parent 데이터 수정</button>
</div>
</template>
<script>
export default {
name: 'ChildAndChild',
model: {
prop: 'sendData',
event: 'event-data'
}
props: ['sendData']
methods: {
showParentLog: function () {
console.log('child 데이터', this.sendData)
},
sendEditData: function () {
console.log('child 데이터 수정 후 전달')
let changeData = this.sendData + 30
this.$emit('event-data', changeData)
}
}
}
</script>
전 방법과 다른 점은 다음과 같습니다.
- 상위 컴포넌트에서 하위 컴포넌트를 설정할때 속성이 v-model 하나로 축소
- 하위 컴포넌트에서 model 속성 객체를 추가하여 설정
Child 컴포넌트에서 버튼으로 로그를 조회해보면
childData
결과는 이전과 동일하게 수정 되는 것을 확인하실수 있습니다.
v-model 은 공식 홈페이지에서도 주로 input 태그나 radio box 등과 같은
반응형 컴포넌트에서 사용을 하라고 주로 소개하고 있었으며
그래서 그런지 v-bind 와 v-on 이 v-model 로 최적화 하는 과정의 데이터 설정과 흐름이 많이 혼란스러웠습니다.
간략하게 나마 정리하니 명확하게 정리가 되네요.
그럼 포스팅 마치겠습니다.
'NodeJS' 카테고리의 다른 글
[NodeJS/VueJS]Nuxt, Vuetify, Quasar 빈도수와 설치 방법 (0) | 2019.11.15 |
---|---|
[NodeJS/VueJS/NuxtJS] Nuxt 에서 Router 경로 설정하기 (0) | 2019.11.08 |
[NodeJS/VueJS/NuxtJS] Nuxt.js 에서 외부라이브러리 연결에 대하여 (vue-owl-carousel 연결) (0) | 2019.11.05 |
[NodeJS/VueJS] Vuex 설치 및 사용 #2 - 심화편 (0) | 2019.11.04 |
[NodeJS/VueJS] Vuex 설치 및 사용 #1 - 기초편 (0) | 2019.11.01 |