Composables in Vue 3 — Riutilizza la Logica come i Custom Hooks di React e Taglia il Codice Duplicato
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Sviluppo di siti web

Composables in Vue 3 — Riutilizza la Logica come i Custom Hooks di React e Taglia il Codice Duplicato

[2026-08-09] Author: Ing. Calogero Bono
> condividi
Zenithby Meteora Web Il sistema operativo della tua attività. Social, clienti, prenotazioni e fatture in un'unica piattaforma. Palestre, barber, professionisti. Scopri Zenith Demo gratis · senza carta

Ti è mai capitato di copiare e incollare la stessa logica di fetch, form validation o gestione del tema in dieci componenti diversi? Il codice duplicato non è solo brutto da vedere: è un costo nascosto. Ogni copia è un punto in cui un bug può nascondersi e ogni modifica richiede dieci interventi manuali. Noi, di Meteora Web, lo vediamo ogni giorno nei progetti che ci arrivano: componenti da mille righe, logica ripetuta, manutenzione che diventa un incubo. Con i Composables in Vue 3, questo problema si risolve alla radice.

Perché i Composables in Vue 3 sono la risposta al codice duplicato?

La Composition API, introdotta con Vue 3, ha portato un paradigma nuovo: la logica può essere estratta in funzioni riutilizzabili che chiamiamo composables. Non sono una libreria esterna, non richiedono plugin: sono semplicemente funzioni JavaScript che usano le API reattive di Vue (ref, reactive, computed, watch) per incapsulare stato e comportamenti.

Pensa a un composable come a una scatola di attrezzi specializzata. Invece di avere un unico cassetto pieno di cacciaviti, martelli e chiodi (il componente), ogni scatola contiene solo ciò che serve per un compito specifico. Vuoi gestire il tema scuro? Prendi la scatola useTheme. Vuoi caricare dati da un'API? Prendi useFetch. Ogni scatola è indipendente, testabile e può essere usata in qualsiasi componente.

La differenza rispetto ai mixin (la soluzione di Vue 2) è sostanziale: i mixin fondevano le proprietà nel componente, creando conflitti di nomi e rendendo difficile capire da dove arrivasse una variabile. I composables, invece, restituiscono esplicitamente ciò che serve, rendendo il codice leggibile e prevedibile. Se conosci i custom hooks di React, sei già a metà strada: la filosofia è identica, ma l'implementazione sfrutta la reattività di Vue.

Come funziona un composable in pratica?

Un composable è una funzione che usa le API di Vue. Ecco un esempio minimo per gestire un contatore:

// composables/useCounter.js
import { ref } from 'vue'

export function useCounter(initialValue = 0) {
  const count = ref(initialValue)

  const increment = () => count.value++
  const decrement = () => count.value--
  const reset = () => count.value = initialValue

  return { count, increment, decrement, reset }
}

In un componente, lo usi così:

Sponsored Protocol




La magia è che count è reattivo: quando cambia, il template si aggiorna automaticamente. E se due componenti usano lo stesso composable, ognuno ha la propria istanza indipendente. Nessuna interferenza, nessun conflitto.

Quali problemi risolve un composable rispetto a un componente?

Un componente può incapsulare logica e template, ma non sempre è la scelta giusta. Se hai una logica che non ha una rappresentazione visiva diretta (come il fetching di dati), costringerla in un componente significa creare wrapper inutili e prop drilling. Un composable, invece, è pura logica: la usi dove ti serve, senza inquinare il template.

Inoltre, i composables sono testabili in isolamento. Puoi scrivere unit test per la logica di fetch o di validazione senza montare un componente, con tempi di esecuzione ridotti e meno complessità. Noi lo facciamo quotidianamente, come abbiamo documentato nella nostra guida su React Testing Library: la stessa filosofia di test mirati si applica perfettamente ai composables Vue.

Come creare un composable useFetch per gestire le chiamate API?

Il caso d'uso più comune è il fetching di dati. Quante volte hai scritto lo stesso codice per caricare dati, gestire lo stato di caricamento e gli errori? Con un composable, lo scrivi una volta sola. Ecco un esempio completo e funzionante:

// composables/useFetch.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useFetch(url, options = {}) {
  const data = ref(null)
  const error = ref(null)
  const isLoading = ref(false)
  let controller = null

  const fetchData = async () => {
    isLoading.value = true
    error.value = null
    controller = new AbortController()

    try {
      const response = await fetch(url, { ...options, signal: controller.signal })
      if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`)
      data.value = await response.json()
    } catch (err) {
      if (err.name !== 'AbortError') error.value = err.message
    } finally {
      isLoading.value = false
    }
  }

  onMounted(fetchData)

  onUnmounted(() => {
    if (controller) controller.abort()
  })

  return { data, error, isLoading, refetch: fetchData }
}

Ora, in qualsiasi componente, puoi caricare dati con poche righe:

Sponsored Protocol




Nota come abbiamo gestito anche l'abort della chiamata quando il componente viene smontato: evitiamo memory leak e richieste inutili. Questo è il livello di attenzione che fa la differenza in produzione.

Come gestire lo stato globale con un composable?

Finora abbiamo visto composables che creano stato locale per ogni componente. Ma se vuoi condividere uno stato tra più componenti (come l'utente autenticato o il carrello), puoi usare un pattern a singleton. Basta definire lo stato al di fuori della funzione:

// composables/useUser.js
import { ref } from 'vue'

const user = ref(null)
const isAuthenticated = computed(() => !!user.value)

export function useUser() {
  const setUser = (newUser) => { user.value = newUser }
  const clearUser = () => { user.value = null }

  return { user, isAuthenticated, setUser, clearUser }
}

Ora, qualsiasi componente che chiama useUser() condivide lo stesso stato. È una soluzione leggera che sostituisce librerie di state management come Pinia per casi semplici. Noi la usiamo spesso per gestire sessioni utente o preferenze di tema.

Quali sono le best practice per scrivere composables robusti?

Scrivere un composable è facile. Scriverlo bene richiede disciplina. Ecco le regole che seguiamo noi, e che ti consigliamo di adottare:

  • Nominalo con "use": la convenzione è universale e rende il codice auto-documentante. useFetch, useLocalStorage, useDebounce, ecc.
  • Restituisci sempre un oggetto: anche se è una sola proprietà, un oggetto permette di aggiungere funzionalità senza rompere il codice esistente.
  • Accetta parametri reattivi: se il tuo composable deve reagire a un cambiamento di input, accetta un ref o usa toRefs per destrutturare. Esempio: useFetch(userId) dove userId è un ref.
  • Pulisci le risorse: se usi event listener, timer o fetch, liberali in onUnmounted. Le risorse dimenticate sono la causa principale di bug subdoli.
  • Documenta i parametri e i valori di ritorno: JSDoc è tuo amico. Un composable ben documentato è un composable che altri (e il te del futuro) useranno senza errori.

Un errore comune è cercare di rendere il composable troppo generico. Un composable che fa tutto è un composable che non fa niente bene. Meglio composables piccoli e focalizzati, che puoi comporre insieme. La composizione è la vera forza di questo pattern.

Sponsored Protocol

Come testare un composable in isolamento?

Testare un composable è semplice: lo chiami in un ambiente controllato e verifichi lo stato. Ecco un esempio con Vitest:

// __tests__/useCounter.spec.js
import { describe, it, expect } from 'vitest'
import { useCounter } from '../composables/useCounter'

describe('useCounter', () => {
  it('incrementa il contatore', () => {
    const { count, increment } = useCounter(5)
    increment()
    expect(count.value).toBe(6)
  })
})

Non serve montare un componente: testi la logica pura, veloce e affidabile. Questo approccio riduce i tempi di test e aumenta la fiducia nel codice. Se vuoi approfondire il testing di componenti, ti consigliamo di leggere la nostra guida su React Testing Library: i principi sono gli stessi, applicati a un altro framework.

Come integrare i composables con TypeScript per una tipizzazione forte?

Se usi TypeScript, i composables diventano ancora più potenti. Puoi definire interfacce per i parametri e i valori di ritorno, rendendo il codice auto-documentante e riducendo gli errori a compile-time. Ecco un esempio tipizzato:

// composables/useLocalStorage.ts
import { ref, watch, type Ref } from 'vue'

export function useLocalStorage(key: string, initialValue: T): [Ref, (value: T) => void] {
  const storedValue = ref(JSON.parse(localStorage.getItem(key) || JSON.stringify(initialValue)))

  const setValue = (value: T) => {
    storedValue.value = value
    localStorage.setItem(key, JSON.stringify(value))
  }

  watch(storedValue, (newValue) => {
    localStorage.setItem(key, JSON.stringify(newValue))
  })

  return [storedValue, setValue]
}

Ora, quando usi questo composable, TypeScript sa che tipo di dato stai gestendo. Niente più errori di runtime dovuti a dati mal formattati. La tipizzazione non è un optional: è un investimento che ripaga in termini di manutenzione e robustezza.

Sponsored Protocol

La documentazione ufficiale di Vue offre ottimi esempi e linee guida. Ti consigliamo di consultarla per approfondire: Composables - Vue.js.

Quali sono i casi d'uso reali che giustificano un composable?

Non tutto merita un composable. La regola d'oro è: se la logica viene usata in più di un componente, estraila. Ecco i casi più frequenti che vediamo nei nostri progetti:

  • Fetching di dati: useFetch, useMutation, useQuery per gestire API.
  • Form validation: useForm per gestire stato, errori e submit.
  • Preferenze utente: useTheme, useLanguage per salvare e ripristinare impostazioni.
  • Geolocalizzazione: useGeolocation per ottenere la posizione e gestire i permessi.
  • Intersection Observer: useIntersectionObserver per lazy loading o animazioni allo scroll.
  • Timer e debounce: useDebounce, useThrottle per ottimizzare eventi ad alta frequenza.

Un esempio concreto che abbiamo implementato per un cliente e-commerce: un composable useCart che gestiva il carrello, sincronizzandolo con il backend e con il localStorage. Un solo punto di modifica per aggiornare prezzi, quantità e disponibilità, e tutti i componenti (header, pagina prodotto, carrello) si aggiornavano automaticamente. Il risultato? Meno bug, sviluppo più rapido e una manutenzione che non faceva paura.

Come evitare gli errori comuni con i composables?

Anche i pattern migliori possono essere usati male. Ecco gli errori che vediamo più spesso:

  • Usare composables per logica che non è riutilizzabile: se lo usi in un solo componente, è over-engineering. Tienilo nel componente.
  • Non gestire la pulizia delle risorse: timer, listener e fetch abbandonati causano memory leak e comportamenti imprevedibili.
  • Ignorare la reattività dei parametri: se passi un valore primitivo, il composable non reagirà ai cambiamenti. Usa ref o toRefs.
  • Creare dipendenze circolari: un composable che usa un altro composable che usa il primo. Evita loop infiniti.
  • Non testare: un composable è logica pura, testalo come tale. Se non lo testi, non sai se funziona.

Noi, di Meteora Web, abbiamo costruito una piattaforma proprietaria per la gestione dei social media usando intensamente i composables. Ogni funzionalità (pubblicazione, calendario, fatturazione) è un composable indipendente, testato e riutilizzabile. Questo ci ha permesso di scalare il progetto senza riscrivere codice, mantenendo una qualità costante.

Sponsored Protocol

Se vuoi vedere come i composables si integrano in un'architettura più ampia, ti consigliamo di leggere la nostra guida su Vue.js 3 e Composition API.

Cosa fare adesso

Ecco le azioni concrete per iniziare a usare i composables oggi stesso:

  1. Identifica il codice duplicato: cerca nei tuoi componenti logica ripetuta (fetch, form, timer). È il candidato perfetto per un composable.
  2. Crea il tuo primo composable: parti da qualcosa di semplice come useCounter o useFetch. Copia gli esempi di questa guida e adattali al tuo caso.
  3. Refactoring incrementale: non riscrivere tutto in un colpo solo. Estrai un composable alla volta, testa e verifica che nulla si rompa.
  4. Scrivi test per i composables: usa Vitest per testare la logica in isolamento. È un investimento che ripaga immediatamente.
  5. Condividi la conoscenza: documenta i tuoi composables e condividili con il team. La coerenza è fondamentale per la manutenibilità.

I composables non sono una moda: sono il modo corretto di scrivere applicazioni Vue 3. Ti permettono di ridurre il codice duplicato, migliorare la testabilità e aumentare la velocità di sviluppo. E, come diciamo sempre, un sito si misura in fatturato, non in complimenti. Meno tempo speso a debuggare significa più tempo per migliorare il prodotto.

> condividi
Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere informatico, fondatore di Meteora Web e Zenith OS. System administrator e progettista di piattaforme, app e CMS proprietari, con esperienza in sviluppo full-stack, marketing digitale ed ecosistema Google.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()