Provide/Inject en Vue.js

0
485

Índice de contenidos

1. Introducción

En este tutorial aprenderemos a usar el sistema de Provide/Inject de Vue.js con Typescript.

Responderemos a algunas preguntas como:

  • ¿Para qué sirve?
  • ¿Para qué no sirve?
  • ¿Cuándo usarlo?

Este tutorial asume un conocimiento intermedio de Vue.

2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • MacBook Pro 15’ (2,5 GHz Intel Core i7, 16GB DDR3)
  • Sistema operativo: macOS Mojave 10.14.4
  • Entorno de desarrollo: Visual Studio Code
  • Versión de Vue: 2.6.10
  • Versión de Typescript: 3.4.3

3. El problema

Si has usado Vue (o cualquier otro framework de front basado en componentes), probablemente hayas sufrido este problema:

  • Tengo un componente padre con propiedad nombre.
  • Tengo un componente hijo, que no quiere saber el nombre de su padre.
  • Tengo un componente nieto, que necesita saber el nombre de su abuelo.

 

¿Cómo le pasamos al nieto, el nombre del padre, sin pasar por el hijo?

4. Provide/Inject

Vue nos proporciona de manera nativa la inyección de dependencias en componentes, llamada Provide/Inject .

  • Un componente puede proveer de algo (un valor, un objeto o una función).
  • Cualquier componente hijo, nieto, etc puede inyectar (leer) ese algo.

 

Ventajas:

  • Centralización de las instancias a usar por los componentes.
  • Inversión de control.
  • Facilita el testing de componentes.

 

Desventajas:

  • No es reactivo*.
  • Puede ocultar el origen de los elementos inyectados.
  • No sigue el estándar prop/event de Vue.

 

Podrías pensar que, todo eso está muy bien, pero si no es reactivo, ¿para qué me sirve? Te recomiendo seguir leyendo hasta la sección de Reactividad.

5. Uso real

En este ejemplo veremos un uso real y útil de Provide/Inject.

Tenemos un par de servicios, LanguageService  y DateService , que uno de nuestros componentes necesita utilizar.

src/services/language

src/services/date

Podríamos crear la instancia en el mismo componente que la va a utilizar, pero no estaríamos siguiendo el concepto de inversión de control. Y nuestro testing sería menos agradable de hacer.

Crear un provider es tan sencillo como:

src/providers/ServiceProvider.vue

La creación de las instancias de nuestros servicios va a estar centralizada en este proveedor. Si algún día estos cambian, solo tendremos que cambiar este archivo.

Todos los componentes que estén dentro del context del <slot>  tendrán acceso a los servicios.

Para dar acceso al componente a los servicios provistos, sólo tenemos que:

src/App.vue

Ahora, todos los componentes dentro de <ServiceProvider>  tendrán acceso a los servicios.

Si vemos el código de <Child> , veremos que es muy sencillo, a propósito:

src/components/Child.vue

Child , el hijo, no utiliza los servicios que su padre ha proveído. Inyectar es totalmente opcional.

Si vemos GrandChild , el nieto, por otro lado:

src/components/GrandChild.vue

Podemos ver que inyectar unas instancias de un proveedor es muy sencillo.

Al poner !  al final una variable le estamos diciendo a Typescript que ésta siempre va a estar inicializada.

Y si vemos los tests de GrandChild , veremos cómo proveer al componente de unas instancia de servicios creadas específicamente para facilitar el test.

src/components/tests/GrandChild.spec.ts


6. Reactividad

Si intentamos hacer Provide()  de un string  que se puede modificar por un <input>:

Y lo inyectamos de esta manera:

La impresión inicial será que el nombre se está renderizando. Pero al cambiar el valor del input, veremos que PersonInfo  no se actualiza.

Esto es porque Provide/Inject no es reactivo con tipos primitivos (number, string, boolean, etc). Si queremos proveer de manera reactiva, debemos hacerlo con una propiedad observable, como una propiedad de un objeto. Por ejemplo:

Teniendo la clase Person:

src/models/Person.ts

Y el proveedor PersonProvider:

src/providers/PersonProvider.vue

Podemos inyectar el objeto en PersonInfo.vue:

src/components/PersonInfo.vue

E incluso podemos encapsular un Provider dentro de otro Provider en App.vue

src/App.vue

Si ahora modificamos el valor del <input> , veremos cómo el componente PersonInfo se actualiza.

Si necesitas más reactividad, échale un vistazo a Vue Reactive Provide.

7. Conclusiones

Provide/Inject en Vue.js nos permite pasar información entre componentes de una manera más limpia que con props , pero tiene unas limitaciones claras.

Su uso está recomendado para la creación de librerías de componentes o plugins. Si no te convence para tu proyecto, échale un vistazo a Vuex.

Todo el código del tutorial está disponible en Github.

8. Referencias

Dejar respuesta

Please enter your comment!
Please enter your name here