Vue.js

Vuejs

Tutorial Vuejs: Uso avanzado de Composables

Vue: Aprende el uso avanzado de composables, incluyendo composición y encadenamiento, inyección de dependencias y manejo de operaciones asíncronas en aplicaciones Vue.

Aprende Vuejs GRATIS y certifícate

Composición y encadenamiento de composables

En Vue, los composables son funciones reutilizables que encapsulan lógica reactiva. La composición de composables permite combinar múltiples composables y crear abstracciones más complejas. El encadenamiento de composables se refiere a la práctica de utilizar la salida de un composable como entrada de otro, lo que permite una orquestación fluida de la lógica.

Para ilustrar la composición, considere un composable que maneja el estado de autenticación de un usuario:

// useAuth.js
import { ref } from 'vue';

export function useAuth() {
  const isAuthenticated = ref(false);

  function login() {
    isAuthenticated.value = true;
  }

  function logout() {
    isAuthenticated.value = false;
  }

  return { isAuthenticated, login, logout };
}

Ahora, imagine que desea crear un nuevo composable que también maneje la autorización basada en roles. Puede componer este nuevo composable utilizando useAuth:

// useRole.js
import { ref } from 'vue';
import { useAuth } from './useAuth';

export function useRole() {
    const role = ref("invitado")

    function changeRoleToAdmin() {
        role.value = "admin";
    }

    return { useAuth, role, changeRoleToAdmin };
}

En este ejemplo, useAuthorization utiliza useAuth para determinar si un usuario está autenticado antes de verificar su rol. Esto demuestra cómo los composables pueden componerse para crear lógica más rica y compleja.

El encadenamiento de composables se puede observar cuando un composable depende de la salida de otro. Por ejemplo, si tiene un composable que maneja la configuración de la aplicación, puede encadenarlo con useAuthorization para condicionar la configuración según el rol del usuario:

<!-- App.vue -->
<template>
    <div ref="div" style="padding: 1em;">
        Tema para el usuario {{ userRole }}
    </div>

    <br>

    <button v-if="!isAuthenticated" @click="register()">Iniciar
        sesión</button>
    <button v-else type="button" @click="changeRoleToAdmin()">Cambiar rol a Admin</button>
    <button type="button" @click="signOut()">Cerrar sesión</button>
</template>

<script setup lang="ts">
  import { computed, ref, watch } from 'vue';
  import { useRole } from '../composables/useRole';

  const div = ref<HTMLElement>();

  const { useAuth, role, changeRoleToAdmin } = useRole();

  const { isAuthenticated, login, logout } = useAuth()

  const canAccessAdmin = computed(() => isAuthenticated.value && role.value === 'admin');
  const userRole = computed(() => role.value)

  function register() {
      login();
      role.value = 'registrado';
  }

  function signOut() {
      logout();
      role.value = 'invitado';
  }

  watch(canAccessAdmin, (newValue) => {
      console.log("el valor ha pasado de: ", canAccessAdmin, " a: ", newValue);
      if (newValue) {
          div.value!.style.background = "black"
          div.value!.style.color = "white"
      } else {
          div.value!.style.background = "white"
          div.value!.style.color = "black"
      }
  });
</script>

Aquí, se observa los cambios en canAccessAdmin de useAuthorization para ajustar la configuración de la aplicación. Este encadenamiento permite que la lógica de configuración reaccione automáticamente a los cambios en la autorización del usuario.

La práctica de componer y encadenar composables facilita la creación de aplicaciones modulares y mantenibles, permitiendo a los desarrolladores dividir la lógica en piezas manejables y reutilizables.

Inyección de dependencias en composables

En Vue, la inyección de dependencias en composables es una técnica que permite a los desarrolladores compartir y gestionar dependencias de manera eficiente a través de los diferentes niveles de la jerarquía de componentes. Esto se logra mediante el uso de las funciones provide y inject, que facilitan el paso de datos o funciones desde un proveedor hasta un consumidor sin necesidad de prop drilling.

Para implementar la inyección de dependencias en composables, primero se define un proveedor que utiliza provide para exponer una dependencia. Luego, en cualquier componente o composable descendiente, se utiliza inject para acceder a esa dependencia.

Ejemplo de uso básico de provide e inject en un composable:

// useThemeProvider.js
import { provide, ref } from 'vue';

export function useThemeProvider() {
  const theme = ref('light');
  
  provide('theme', theme);
  
  return { theme };
}

En este ejemplo, useThemeProvider es un composable que define un estado reactivo theme y lo proporciona a través del árbol de componentes. Cualquier componente descendiente puede inyectar este theme y reaccionar a sus cambios.

Para consumir esta dependencia en un composable o componente, se utiliza inject de la siguiente manera:

// useThemeConsumer.js
import { inject } from 'vue';

export function useThemeConsumer() {
  const theme = inject('theme', ref('defaultTheme'));
  
  return { theme };
}

Aquí, useThemeConsumer inyecta el theme proporcionado. En caso de que no haya un proveedor en la jerarquía, se utilizará el valor predeterminado defaultTheme.

La inyección de dependencias es especialmente útil en aplicaciones grandes o complejas, donde es necesario compartir configuraciones o servicios entre múltiples componentes sin crear dependencias fuertes. No obstante, se debe usar con cuidado para evitar la creación de dependencias ocultas que puedan dificultar la comprensión del flujo de datos en la aplicación.

En situaciones avanzadas, como la inyección de servicios o instancias de clases, se puede proporcionar e inyectar funciones o clases completas, lo que permite un alto grado de flexibilidad y modularidad. Aquí un ejemplo de cómo inyectar un servicio:

// loggerService.js
export class LoggerService {
  log(message: string) {
    console.log('Log:', message);
  }
}
// useLoggerProvider.js
import { provide } from 'vue';
import { LoggerService } from '../../services/loggerServices';

export function useLoggerProvider() {
  provide('logger', new LoggerService());
}
// useLoggerConsumer.js
import { inject } from 'vue';
import { LoggerService } from '../../services/loggerServices';

export function useLoggerConsumer() {
  const logger = inject<LoggerService>("logger", new LoggerService());
  
  function logMessage(message: string) {
    if (logger) {
      logger.log(message);
    }
  }
  
  return { logMessage };
}

En este caso, useLoggerProvider proporciona una instancia de LoggerService, y useLoggerConsumer inyecta y utiliza el servicio para registrar mensajes. Este enfoque permite mantener el código modular y reutilizable, facilitando la gestión de dependencias en aplicaciones Vue.

Creación de composables con async y await

En Vue, los composables son funciones reutilizables que encapsulan lógica reactiva y permiten estructurar el código de manera más modular. Al integrar async y await en composables, se puede gestionar de forma eficiente la lógica asíncrona, como llamadas a API, dentro de una aplicación Vue.

Para crear un composable que maneje operaciones asíncronas, es crucial definir la función del composable como async. Esto permite utilizar await dentro de la función para esperar la resolución de promesas antes de continuar con la ejecución. Aquí se muestra cómo definir un composable asíncrono:

// useFetchData.js
import { ref } from 'vue';

export async function useFetchData(url) {
  const data = ref(null);
  const error = ref(null);

  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    data.value = await response.json();
  } catch (err) {
    error.value = err.message;
  }

  return { data, error };
}

En este ejemplo, useFetchData es un composable que realiza una solicitud HTTP para obtener datos desde un url proporcionado. Utiliza await para esperar la respuesta de la función fetch y maneja errores potenciales mediante un bloque try-catch. Los valores de data y error se definen como referencias reactivas que pueden ser utilizadas en componentes para reaccionar a los cambios de estado.

Para utilizar este composable en un componente Vue, se puede hacer de la siguiente manera:

// DataDisplayComponent.vue
<template>
  <div>
    <div v-if="error">{{ error }}</div>
    <div v-else-if="data">
      <pre>{{ data }}</pre>
    </div>
    <div v-else>Cargando...</div>
  </div>
</template>

<script setup>
import { onMounted } from 'vue';
import { useFetchData } from './useFetchData.js';

const { data, error } = await useFetchData('https://api.example.com/data');

onMounted(() => {
  // Lógica adicional si es necesario al montar el componente
});
</script>

En este componente DataDisplayComponent.vue, se utiliza el composable useFetchData para obtener datos de una API. La llamada a useFetchData se realiza con await para asegurar que los datos se cargan antes de que el componente se monte completamente, y se gestiona el estado de carga con un simple condicional en la plantilla.

Es importante tener en cuenta que, aunque async y await hacen que el código asíncrono sea más fácil de leer y escribir, se debe gestionar adecuadamente el estado de carga y los errores para proporcionar una experiencia de usuario fluida. Además, debido a que las funciones de setup en componentes de composición no pueden ser asíncronas, cualquier lógica asíncrona debe manejarse dentro de funciones auxiliares o composables como se muestra en los ejemplos anteriores.

El uso de composables con async y await en Vue mejora la legibilidad del código y facilita la gestión de tareas asíncronas, manteniendo la reactividad y modularidad del código.

Aprende Vuejs GRATIS online

Ejercicios de esta lección Uso avanzado de Composables

Evalúa tus conocimientos de esta lección Uso avanzado de Composables con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de Vuejs

Accede a todas las lecciones de Vuejs y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Vue Y Su Ecosistema

Vue.js

Introducción Y Entorno

Instalar Y Configurar Vue Con Vite

Vue.js

Introducción Y Entorno

Introducción A La Sintaxis De Plantillas

Vue.js

Componentes

Introducción A Componentes

Vue.js

Componentes

Componentes Con Options Api

Vue.js

Componentes

Componentes Con Composition Api

Vue.js

Componentes

Renderizado Condicional Con V-if

Vue.js

Componentes

Renderizado Iterativo Con V-for

Vue.js

Componentes

Props Y Comunicación Entre Componentes

Vue.js

Componentes

Manejo De Eventos En Vue Con V-on

Vue.js

Componentes

Binding Bidireccional Con V-model Y Definemodel

Vue.js

Componentes

Estilización De Componentes

Vue.js

Componentes

Reactividad Con Ref Y Reactive

Vue.js

Composición Y Reactividad

Ciclo De Vida Con Composition Api

Vue.js

Composición Y Reactividad

Composition Api: Provide E Inject

Vue.js

Composición Y Reactividad

Introducción A Los Composables

Vue.js

Composición Y Reactividad

Uso Avanzado De Composables

Vue.js

Composición Y Reactividad

Introducción A Vue Router

Vue.js

Navegación Y Enrutamiento

Definición Y Manejo De Rutas

Vue.js

Navegación Y Enrutamiento

Rutas Anidadas Y Dinámicas

Vue.js

Navegación Y Enrutamiento

Navegación Programática Y Redirección

Vue.js

Navegación Y Enrutamiento

Solicitudes Http Con Fetch Api

Vue.js

Interacción Http Con Apis De Backend

Solicitudes Http Con Axios

Vue.js

Interacción Http Con Apis De Backend

Introducción A Suspense

Vue.js

Interacción Http Con Apis De Backend

Evaluación Test De Conocimientos Vuejs

Vue.js

Evaluación

Accede GRATIS a Vuejs y certifícate

Certificados de superación de Vuejs

Supera todos los ejercicios de programación del curso de Vuejs y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Componer y encadenar múltiples composables.
  2. Utilizar inyección de dependencias con provide e inject.
  3. Manejar operaciones asíncronas con async y await en composables.
  4. Implementar patrones avanzados de reutilización de lógica en Vue.