Guida Completa alla Vue Composition API: Architettura, Reattività e Pattern Avanzati

Intermedio
JavaScript Vue.js

Scopri come rivoluzionare l'organizzazione del codice in Vue.js utilizzando la Composition API per creare componenti scalabili, riutilizzabili e tipizzati.

Pubblicato
Tag
Web Development javascript frontend Vue.js composition-api reactivity

Introduzione alla Composition API

Per anni, l'Options API è stata il cuore di Vue.js, offrendo una struttura chiara e guidata attraverso proprietà come data, methods, computed e watch. Tuttavia, man mano che le applicazioni crescevano in complessità, gli sviluppatori si scontravano con un problema fondamentale: la frammentazione della logica. In un componente di grandi dimensioni, la logica relativa a una singola funzionalità (ad esempio, la gestione di un modulo di ricerca) finiva per essere sparsa tra diverse sezioni dell'oggetto di opzioni, rendendo il codice difficile da leggere e mantenere.

La Composition API, introdotta con Vue 3, nasce per risolvere esattamente questo problema. Non sostituisce l'Options API, ma offre un modo alternativo e più flessibile di organizzare la logica del componente. Invece di definire il comportamento in base a "dove va il codice" (metodo o dato), lo definiamo in base a "cosa fa il codice".

Perché passare alla Composition API?

Il vantaggio principale è la riutilizzabilità. Con l'Options API, l'unico modo per condividere logica tra componenti era l'utilizzo dei Mixins, che però introducevano problemi di collisione dei nomi e rendevano opaca la provenienza di certe proprietà. La Composition API introduce i Composables, funzioni esterne che incapsulano logica reattiva e possono essere importate in qualsiasi componente, rendendo il flusso di dati esplicito e tracciabile.

I Pilastri della Reattività: ref() e reactive()

Al centro della Composition API c'è il sistema di reattività. Per rendere un dato "reattivo" (ovvero fare in modo che Vue aggiorni automaticamente il DOM quando il valore cambia), utilizziamo due funzioni principali: ref e reactive.

Quando usare ref()

ref è l'approccio più versatile. Crea un oggetto reattivo che avvolge un valore primitivo (stringa, numero, booleano) o un oggetto. La caratteristica fondamentale è che, per accedere o modificare il valore all'interno del JavaScript, è necessario utilizzare la proprietà .value.

import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const name = ref('Sviluppatore');

    const increment = () => {
      count.value++; // Accesso tramite .value
    };

    return { count, name, increment };
  }
};

Quando usare reactive()

reactive accetta solo oggetti (o array) e crea una copia reattiva profonda. A differenza di ref, non richiede l'uso di .value.

import { reactive } from 'vue';

export default {
  setup() {
    const state = reactive({
      user: 'Mario Rossi',
      isLoggedIn: false,
      settings: { theme: 'dark' }
    });

    const login = () => {
      state.isLoggedIn = true;
    };

    return { state, login };
  }
};

Attenzione: Un errore comune con reactive è il tentativo di destrutturare l'oggetto. Se scriviamo const { user } = state, la variabile user perde la reattività perché diventa una semplice stringa. Per mantenere la reattività durante la destrutturazione, è necessario usare toRefs().

Il ciclo di vita e le Computed Properties

Nella Composition API, i hook del ciclo di vita vengono importati come funzioni. Ad esempio, mounted() diventa onMounted(), e updated() diventa onUpdated(). Questi hook devono essere chiamati all'interno della funzione setup (o nel blocco <script setup>).

Proprietà Computate

Le computed properties rimangono fondamentali per derivare valori da altri stati reattivi senza ricalcolarli a ogni render. Vengono create tramite la funzione computed().

import { ref, computed } from 'vue';

export default {
  setup() {
    const firstName = ref('Luca');
    const lastName = ref('Bianchi');

    const fullName = computed(() => {
      return `${firstName.value} ${lastName.value}`;
    });

    return { firstName, lastName, fullName };
  }
};

L'approccio moderno:

Sebbene la funzione setup() sia il cuore della Composition API, Vue ha introdotto una sintassi più concisa chiamata <script setup>. Questa è attualmente la raccomandazione ufficiale per la maggior parte dei progetti.

Con <script setup>, non è più necessario esportare un oggetto o restituire manualmente le variabili per renderle disponibili al template. Tutto ciò che è dichiarato nel blocco script è automaticamente disponibile nel template.

<template>
  <div>
    <p>Contatore: {{ count }}</p>
    <button @click="increment">Incrementa</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// Definizione semplice e diretta
const count = ref(0);
const increment = () => count.value++;
</script>

Questo approccio riduce drasticamente il "boilerplate" (codice ripetitivo) e migliora le performance di compilazione, poiché Vue può ottimizzare meglio il rendering.

Creare Composables: La vera potenza di Vue 3

Un Composable è una funzione che utilizza la Composition API per incapsulare e riutilizzare logica reattiva. Immaginiamo di voler gestire la posizione dell'utente tramite l'API del browser in più componenti diversi.

Esempio Pratico: useMousePosition

Creiamo un file composables/useMouse.js:

import { ref, onMounted, onUnmounted } from 'vue';

export function useMouse() {
  const x = ref(0);
  const y = ref(0);

  function updatePosition(event) {
    x.value = event.pageX;
    y.value = event.pageY;
  }

  onMounted(() => window.addEventListener('mousemove', updatePosition));
  onUnmounted(() => window.removeEventListener('mousemove', updatePosition));

  return { x, y };
}

Ora possiamo utilizzare questo composable in qualsiasi componente con una semplicità estrema:

<template>
  <div>Il mouse si trova in: {{ x }}, {{ y }}</div>
</template>

<script setup>
import { useMouse } from './composables/useMouse';

const { x, y } = useMouse();
</script>

Questo pattern permette di separare la logica di business dalla logica di presentazione, rendendo i componenti estremamente leggeri e focalizzati solo sul rendering.

Errori Comuni e Best Practices

1. Dimenticare .value

È l'errore più frequente per chi proviene dall'Options API. Ricorda: all'interno del template, Vue "unwraps" automaticamente i ref, quindi non serve .value. Ma nel JavaScript, è obbligatorio.

2. Over-use di reactive()

Molti sviluppatori tendono a usare reactive per tutto. Tuttavia, ref è generalmente preferibile perché è più esplicito e funziona con ogni tipo di dato. L'uso di ref rende chiaro a colpo d'occhio quale variabile è reattiva e quale no.

3. Logica troppo complessa nei componenti

Anche con la Composition API, è facile scrivere componenti giganti. La regola d'oro è: se un blocco di logica supera le 20-30 righe o è potenzialmente riutilizzabile, spostalo in un composable esterno.

Confronto Finale: Options API vs Composition API

Caratteristica Options API Composition API
Organizzazione Per opzione (data, methods...) Per funzionalità logica
Riutilizzo Mixins (rischiosi) Composables (espliciti)
TypeScript Supporto limitato Supporto nativo e eccellente
Curva di apprendimento Bassa (molto intuitiva) Media (richiede comprensione della reattività)
Scalabilità Difficile in componenti grandi Ideale per applicazioni enterprise

Prossimi Passi

Ora che hai compreso le basi della Composition API, ti consigliamo di approfondire i seguenti argomenti per diventare un esperto di Vue 3:

  1. Pinia: Il nuovo store management ufficiale che sfrutta appieno la Composition API per gestire lo stato globale.
  2. Teleport e Suspense: Nuovi componenti integrati per gestire l'inserimento di elementi fuori dal DOM principale e gli stati di caricamento asincroni.
  3. Vue Router 4: Impara come integrare la navigazione con i composables tramite useRoute e useRouter.
  4. TypeScript con Vue: La Composition API è progettata per TypeScript. Prova a tipizzare i tuoi ref e i tuoi composables per ridurre gli errori in fase di runtime.

La Composition API non è solo un cambiamento di sintassi, ma un cambio di paradigma che sposta Vue verso un modello di programmazione più funzionale e modulare, rendendolo competitivo con i framework più moderni e robusti del mercato.