# Provide / Inject
Esta sección utiliza componentes de un solo archivo para ejemplos de códigos
Esta guía asume que usted ya ha leído Provide / Inject, la Introducción de la API de Composición, Fundamentos de la Reactividad.
También podemos utilizar provide / inject con la API de Composición. Ambos solo pueden ser invocados durante el setuo()
con una instance activa actual.
# Explicación del Escenario
Asumamos que queremos reescribir el siguiente código, el cual contiene un componente MyMap
que proporciona a un componente MyMarker
la ubicación del usuario, utilizando la API de Composición.
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
provide: {
location: 'Polo Norte',
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
# Utilizar Provide
Cuando se utiliza provide
dentro de setup()
, comenzamos importando este método desde Vue
de forma explícita. Esto nos permite definir cada propiedad con su propia invocación de provide
.
La función provide
le permite definir la propiedad a través de dos parámetros:
- El nombre de la propiedad (de tipo
<String>
) - El valor de la propiedad
Utilizando nuestro componente MyMap
, nuestro valores proporcionado (provided) pueden ser refactorizados de la siguiente forma:
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide } from 'vue'
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
setup() {
provide('location', 'Polo Norte')
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
# Utilizar Inject
Cuando se utilizada inject
dentro de setuo()
, también debemos importarlo desde Vue
de forma explícita. Una vez que lo hagamos, nos permitirá invocarlo para definir cómo queremos exponerlo a nuestro componente.
La función inject
recibe dos parámetros:
- El nombre de la propiedad a inyectar
- Un valor por defecto (Opcional)
Utilizando nuestro componente MyMarker
, podemos refactorizar nuestro código de la siguiente forma:
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'
export default {
setup() {
const userLocation = inject('location', 'El Universo')
const userGeolocation = inject('geolocation')
return {
userLocation,
userGeolocation
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Reactividad
# Agregar Reactividad
Para agregar reactividad entre valores proporcionados (provided) e inyectados (injected), podemos utilizar ref o reactive cuando proveemos un valor.
Utilizando nuestro componente MyMap
, podemos actualizar nuestro código de la siguiente forma:
<!-- 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('Polo Norte')
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
Ahora, si algo cambia en cualquiera de las propiedades, el componente MyMarker
también se actualizará automáticamente!
# Mutar Propiedades Reactivas
Al utilizar valores provide / inject reactivos, se recomienda que las mutaciones a propiedades reactivas se realicen dentro del provider siempre que sea posible.
Por ejemplo, en el evento necesitabamos cambiar la ubicación del usuario, idealmente haríamos esto dentro del componente 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('Polo Norte')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
provide('location', location)
provide('geolocation', geolocation)
return {
location
}
},
methods: {
updateLocation() {
this.location = 'Polo Sur'
}
}
}
</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
Sin embargo, hay ocasiones en los que necesita actualizar el dato dentro del componente en el que el mismo fue inyectado. En este escenario, recomendamos proveer un método que sea responsable de mutar la propiedad reactiva.
<!-- 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('Polo Norte')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'Polo Sur'
}
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', 'El Universo')
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
Finalmente, recomendamos el uso de readonly
en propiedades proporcionadas (provided) si usted quiere asegurarse que el dato pasado a través de provide
no pueda ser mutado por el componente que lo inyecte.
<!-- 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('Polo Norte')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'Polo Sur'
}
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