# 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>
1
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>
1
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:

  1. El nombre de la propiedad (de tipo <String>)
  2. 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>
1
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:

  1. El nombre de la propiedad a inyectar
  2. 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>
1
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>
1
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>
1
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>
1
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>
1
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>
1
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