Skip to content

Composables — Visión General

Los composables son funciones que encapsulan lógica reactiva reutilizable. Son el mecanismo principal para compartir comportamiento entre componentes sin herencia ni mixins. En Vue 3 con Composition API, reemplazan completamente a los mixins de Vue 2.

En este proyecto hay 26+ composables. Se auto-importan — no necesitas escribir import, solo los invocas directamente:

const { data, isPending } = useServices('getCourses')
const { showAlert } = useShowAlert()
const { showModal, useOpenModal } = useModal()

Estos son los composables que usarás constantemente. Cada uno tiene su propia página de documentación con ejemplos detallados:

ComposablePropósitoCuándo lo necesitas
useServicesObtener datos del backend con fallback i18nSiempre que muestres datos del CMS
useShowAlertMostrar toasts de éxito/error/warningTras operaciones de usuario, errores de API
useBuyFlowOrquestar el flujo de compra completoBotones de “Comprar”, cards de producto
useFormGestión de formularios con validaciónRegistro, perfil, contacto, checkout
useModalControlar apertura/cierre de modalesCualquier popup, confirmación, o overlay
useGlobalSearchBúsqueda con debounce y filtrado reactivoBarra de búsqueda, filtros de listados
useLocalesCargar traducciones JSON por páginaContenido de páginas, secciones largas
useCheckoutCrear sesiones de StripeInternamente por useBuyFlow — raro usarlo directo
useLanguageChangerCambiar idioma global del usuarioSelector de idioma en la navbar

Composables de ecom-components (auto-importados)

Section titled “Composables de ecom-components (auto-importados)”

La librería @alebat-education/ecom-components también exporta composables que se registran automáticamente:

ComposablePropósitoEjemplo de uso
useCardBehavior()Estados de interacción de cards (hover, pressed, focus)Animaciones de cards personalizadas
useCustomSwiper()Configuración pre-armada para sliders con SwiperCarruseles de productos, media galleries
usePdfEngine()Motor de renderizado de PDFs (pdfjs-dist)Lector de libros digitales
useTimerCountdown()Cuenta regresiva con limpieza automática al desmontarEventos en vivo, ofertas temporales

Estos NO están en la carpeta composables/ del proyecto — vienen del paquete. Los documentamos aquí para que sepas que existen.


Composables que NO deberías llamar directamente

Section titled “Composables que NO deberías llamar directamente”

Algunos composables son internos — los usan otros composables o el sistema, no tú:

ComposableLo usaPor qué no llamarlo directo
useCheckoutuseBuyFlowEl buy flow maneja toda la orquestación; checkout solo es un paso
useElevenLabsAgentSistema de chat AIConfiguración compleja de agente, no tiene sentido standalone

Crea un composable cuando:

  • La lógica se repite en 2+ componentes — el caso más claro. Si copias y pegas un bloque de refs + computeds + watchers, es candidato a composable.
  • Un componente tiene demasiadas responsabilidades — si un layout tiene 300+ líneas de <script setup>, extrae bloques lógicos coherentes a composables.
  • Necesitas compartir estado reactivo entre hermanos — cuando dos componentes que no son padre/hijo necesitan reaccionar al mismo estado (sin usar un store global).
  • La lógica involucra efectos secundarios complejos — timers, event listeners, WebSocket connections, intersection observers. Un composable puede manejar el cleanup automáticamente con onUnmounted.

No crees un composable si:

  • Solo necesitas una función pura (eso es un util, no un composable)
  • El estado solo lo necesita un componente (déjalo inline en el componente)
  • Ya existe un composable que hace lo mismo (revisa la lista arriba primero)

composables/useWebinarFilters.ts
export const useWebinarFilters = () => {
// 1. Estado reactivo
const searchQuery = ref('')
const selectedCategory = ref<string | null>(null)
const results = ref<WebinarItem[]>([])
// 2. Computeds derivados
const filteredResults = computed(() => {
let filtered = results.value
if (searchQuery.value) {
filtered = filtered.filter(w =>
w.title.toLowerCase().includes(searchQuery.value.toLowerCase())
)
}
if (selectedCategory.value) {
filtered = filtered.filter(w => w.category === selectedCategory.value)
}
return filtered
})
const hasResults = computed(() => filteredResults.value.length > 0)
// 3. Métodos / acciones
function clearFilters() {
searchQuery.value = ''
selectedCategory.value = null
}
// 4. Retorna solo lo que el consumidor necesita
return {
searchQuery,
selectedCategory,
filteredResults,
hasResults,
clearFilters,
}
}

Reglas:

  • Siempre empieza con use + nombre descriptivo en PascalCase
  • Exporta como export const useNombre = () => { ... }
  • Retorna un objeto con las refs, computeds y funciones que el consumidor necesita
  • No necesitas registrarlo — Nuxt lo auto-importa al estar en composables/

Diferencia entre composable, util, y servicio

Section titled “Diferencia entre composable, util, y servicio”
ComposableUtilServicio
Ubicacióncomposables/utils/services/
Usa reactividadSí (ref, computed, watch)No — funciones purasNo directamente
Auto-importadoSíSíNo (se accede via useServices)
EjemplouseForm(), useModal()formatDate(), slugify()getCourses(), getUserLogin()
Convención de nombreuseAlgonombreFunciongetNombreRecurso