# Provide / Inject
В разделе в примерах кода используется синтаксис однофайловых компонентов
Подразумевается, что уже изучили и разобрались с разделами Provide / Inject, Введение в Composition API и Основы реактивности. Если нет — прочитайте их сначала.
Можно использовать provide / inject и вместе с Composition API. Они могут быть вызваны во время setup()
с текущим активным экземпляром.
# Предыстория сценария использования
Предположим, что нужно переписать следующий код с использованием Composition API, где компонент MyMap
предоставляет текущее местоположение компоненту MyMarker
.
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
provide: {
location: 'Северный полюс',
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
Для использования provide
в setup()
потребуется сначала явно импортировать метод из vue
. Это позволяет определить каждое свойство своим собственным вызовом provide
.
Функция provide
позволяет определить свойство с помощью двух аргументов:
- Имя свойства (тип
<String>
) - Значение свойства
Внедряемые значения в компоненте MyMap
можно переписать следующим образом:
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide } from 'vue'
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
setup() {
provide('location', 'Северный полюс')
provide('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
22
# Использование Inject
Для использования inject
в setup()
также потребуется сначала явно импортировать метод из vue
. После этого его можно будет вызывать, чтобы определить какие свойства требуется внедрить в компоненте.
Функция inject
принимает два аргумента:
- Имя внедряемого свойства
- Значение по умолчанию (опционально)
Код в компоненте MyMarker
можно переписать следующим образом:
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'
export default {
setup() {
const userLocation = inject('location', 'Вселенная')
const userGeolocation = inject('geolocation')
return {
userLocation,
userGeolocation
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Реактивность
# Добавление реактивности
Чтобы сохранить реактивность между предоставляемыми и внедряемыми значениями можно воспользоваться 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('Северный полюс')
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 рекомендуется сохранять любые мутации реактивных свойств внутри провайдера во всех случаях, когда это возможно.
Например, если потребуется изменять местоположение пользователя, то лучшим способом будет это делать внутри компонента 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('Северный полюс')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
provide('location', location)
provide('geolocation', geolocation)
return {
location
}
},
methods: {
updateLocation() {
this.location = 'Южный полюс'
}
}
}
</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
Но иногда требуется обновлять данные внутри компонента, в который внедряются данные. В таком случае лучше предоставлять метод, который будет изменять реактивное свойство.
<!-- 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('Северный полюс')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'Южный полюс'
}
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', 'Вселенная')
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
Также рекомендуется использовать readonly
на предоставляемых свойствах, если нужно гарантировать, чтобы передаваемые через provide
данные не изменялись компонентом, в который внедряются.
<!-- 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('Северный полюс')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'Южный полюс'
}
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