# 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