# Provide / Inject
이 가이드는 Provide / Inject, Composition API Introduction 와 Reactivity Fundamentals 를 이미 읽었다고 가정합니다.
Composition API와 함께 provide / inject를 사용할 수 있습니다. provide / inject는 현재 활성화된 인스턴스의 setup()
중에 호출 될 수 있습니다.
# 시나리오 배경
Composition API를 사용하여, 사용자의 위치를 가진 MyMarker
컴포넌트에 provide하는 MyMap
컴포넌트가 포함된 다음과 같은 코드를 재작성한다고 가정하겠습니다.
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
provide: {
location: 'North Pole',
geolocation: {
longitude: 90,
latitude: 135
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- src/components/MyMarker.vue -->
<script>
export default {
inject: ['location', 'geolocation']
}
</script>
2
3
4
5
6
# Provide 사용하기
setup()
안에서 provide
를 사용할 때, vue
에서 메소드를 명시적으로 import함으로서 시작합니다. 이를 통해 고유한 provide
호출로 각 속성을 정의할 수 있습니다.
provide
펑션은 2개의 전달인자를 통해 속성을 정의할 수 있습니다:
- 속성명 (
<String>
타입) - 속성값
provide된 값과 inject된 값 사이의 반응성을 유지하기 위해서, 값을 provide 할 때 ref나 reactive를 사용할 수 있습니다:
import { ref, reactive } from 'vue'
// in provider
setup() {
const book = reactive({
title: 'Vue 3 Guide',
author: 'Vue Team'
})
const year = ref('2020')
provide('book', book)
provide('year', year)
}
// in consumer
setup() {
const book = inject('book')
const year = inject('year')
return { book, year }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Inject 사용하기
이제, provider 컴포넌트에서 book
이나 year
가 변경되면, inject하는 컴포넌트에서 변경사항을 감지할 수 있습니다.
WARNING
injected된 반응형 속성을 변경하는 것은 Vue의 단방향 데이터 흐름을 깨기 때문에 추천하지 않습니다. 대신, provide된 값을 변경하거나 변경하는 메소드를 provide하세요.
- inject할 속성명
- 기본값 (선택사항)
MyMarker
컴포넌트를 사용하여, 다음과 같은 코드로 리펙토링을 할 수 있습니다:
import { ref, reactive } from 'vue'
// in provider
setup() {
const book = reactive({
title: 'Vue 3 Guide',
author: 'Vue Team'
})
function changeBookName() {
book.title = 'Vue 3 Advanced Guide'
}
provide('book', book)
provide('changeBookName', changeBookName)
}
// in consumer
setup() {
const book = inject('book')
const changeBookName = inject('changeBookName')
return { book, changeBookName }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 반응성
# 반응성 추가
provide된 값과 inject된 값 사이에 반응성을 추가하기 위해, 값을 provide할 때 ref 나 reactive 를 사용할 수 있습니다.
MyMap
컴포넌트를 사용하여 아래와 같이 코드를 업데이트할 수 있습니다:
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
provide('location', location)
provide('geolocation', geolocation)
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
이제, 두 속성 중 하나가 변경되면, MyMarker
컴포넌트는 자동으로 업데이트됩니다!
# 반응성 속성 변경하기
반응성있는 provide / inject값을 사용하는 경우, 가능하면 provider 내부에 반응성있는 속성에 대한 변이를 유지하는 것이 좋습니다.
예를들면, 사용자의 위치를 변경해야하는 경우, 이상적으로 MyMap
컴포넌트 내에 이 작업을 수행합니다.
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
provide('location', location)
provide('geolocation', geolocation)
return {
location
}
},
methods: {
updateLocation() {
this.location = 'South Pole'
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
그러나, 데이터가 inject된 컴포넌트 내부의 데이터를 업데이트해야하는 경우가 있습니다. 이 시나리오에서는 반응형있는 속성을 변경하는 방법을 메소드를 제공하는 것이 좋습니다.
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'South Pole'
}
provide('location', location)
provide('geolocation', geolocation)
provide('updateLocation', updateLocation)
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'
export default {
setup() {
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')
const updateUserLocation = inject('updateLocation')
return {
userLocation,
userGeolocation,
updateUserLocation
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
마지막으로, provide
를 통해 전달된 데이터가 inject된 컴포넌트에 의해 변경되지 않도록 하려면, provide 속성에 readonly
를 사용하는 것이 좋습니다.
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, readonly, ref } from 'vue'
import MyMarker from './MyMarker.vue
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'South Pole'
}
provide('location', readonly(location))
provide('geolocation', readonly(geolocation))
provide('updateLocation', updateLocation)
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30