Vai al contenuto principale

[Easy] Nuove Funzionalità di Vue3

1. Quali sono le nuove funzionalità di Vue 3?

Quali sono le principali nuove funzionalità di Vue 3?

Vue 3 ha introdotto molteplici importanti aggiornamenti:

Funzionalità principali

  1. Composition API
  2. Teleport
  3. Fragment (nodi root multipli)
  4. Suspense
  5. Binding v-model multipli
  6. Migliore supporto TypeScript
  7. Miglioramenti delle prestazioni (bundle più piccolo, rendering più veloce)

2. Teleport

Cos'è Teleport?

Teleport permette di renderizzare parte di un componente in un'altra posizione nell'albero DOM senza cambiare la struttura logica o la proprietà del componente.

Casi d'uso tipici

Modal, Tooltip, Notification, Popover, livelli overlay.

<template>
<div>
<button @click="showModal = true">Apri Modal</button>

<Teleport to="body">
<div v-if="showModal" class="modal">
<div class="modal-content">
<h2>Titolo del Modal</h2>
<p>Contenuto del Modal</p>
<button @click="showModal = false">Chiudi</button>
</div>
</div>
</Teleport>
</div>
</template>

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

const showModal = ref(false);
</script>

Perché Teleport è utile

  1. Risolve problemi di stacking context / z-index
  2. Evita il clipping causato dall'overflow degli antenati
  3. Mantiene la logica del componente collocata insieme mentre renderizza altrove

3. Fragment (Nodi Root Multipli)

Cos'è Fragment in Vue 3?

Vue 3 permette al template di un componente di avere nodi root multipli. A differenza di React, Vue utilizza fragment impliciti (nessun tag <Fragment> aggiuntivo necessario).

Vue 2 vs Vue 3

Vue 2: root singolo obbligatorio.

<template>
<div>
<h1>Titolo</h1>
<p>Contenuto</p>
</div>
</template>

Vue 3: root multipli permessi.

<template>
<h1>Titolo</h1>
<p>Contenuto</p>
</template>

Perché Fragment è importante

  1. Meno elementi wrapper non necessari
  2. HTML semantico migliore
  3. Albero DOM meno profondo
  4. Stile e selettori più puliti

Ereditarietà degli attributi nei componenti multi-root

Con template multi-root, gli attributi del genitore (class, id, ecc.) non vengono applicati automaticamente a un root specifico. Usare $attrs manualmente.

<!-- Genitore -->
<MyComponent class="custom-class" id="my-id" />

<!-- Figlio -->
<template>
<div v-bind="$attrs">Primo root</div>
<div>Secondo root</div>
</template>

Puoi controllare il comportamento con:

<script setup>
defineOptions({
inheritAttrs: false,
});
</script>

Fragment vs React Fragment

CaratteristicaVue 3 FragmentReact Fragment
SintassiImplicito (nessun tag necessario)Esplicito (<> o <Fragment>)
Gestione keyRegole normali vnode/key nelle listeKey supportata su <Fragment key=...>
Inoltro attrUsare $attrs manualmente in multi-rootNessun attr diretto sui fragment

4. Suspense

Cos'è Suspense?

Suspense è un componente integrato per gli stati di caricamento delle dipendenze asincrone. Renderizza una UI di fallback mentre il componente/setup asincrono si risolve.

Utilizzo base

<template>
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>Caricamento...</div>
</template>
</Suspense>
</template>

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

const AsyncComponent = defineAsyncComponent(() =>
import('./AsyncComponent.vue')
);
</script>

Casi d'uso tipici

  1. Caricamento di componenti asincroni
  2. Requisiti di dati setup() asincroni
  3. UI skeleton a livello di route o sezione

5. v-model Multipli

Binding v-model multipli

Vue 3 supporta binding v-model multipli su un singolo componente. Ogni binding mappa su una prop + evento update:propName.

Vue 2 vs Vue 3

Vue 2: un solo pattern v-model per componente.

<CustomInput v-model="value" />

Vue 3: binding v-model multipli con nome.

<CustomForm
v-model:username="username"
v-model:email="email"
v-model:password="password"
/>

Esempio di implementazione del componente

<!-- CustomForm.vue -->
<template>
<div>
<input
:value="username"
@input="$emit('update:username', $event.target.value)"
/>
<input
:value="email"
@input="$emit('update:email', $event.target.value)"
/>
<input
:value="password"
@input="$emit('update:password', $event.target.value)"
/>
</div>
</template>

<script setup>
defineProps(['username', 'email', 'password']);
defineEmits(['update:username', 'update:email', 'update:password']);
</script>

6. Domande Comuni nei Colloqui

Domande comuni nei colloqui

Domanda 1: quando dovresti usare Teleport?

Clicca per vedere la risposta

Usare Teleport quando il rendering visuale deve sfuggire ai vincoli del DOM locale:

  1. Dialog modali per evitare problemi di stacking/overflow del genitore
  2. Tooltip/popover che non dovrebbero essere tagliati
  3. Notifiche globali renderizzate in un container root dedicato

Evitare Teleport per contenuto normale in-flow.

Domanda 2: vantaggi di Fragment

Clicca per vedere la risposta

Vantaggi:

  1. meno nodi wrapper
  2. migliore struttura semantica
  3. CSS più semplice in molti layout
  4. meno profondità DOM e sovraccarico

Domanda 3: ereditarietà degli attributi multi-root

Clicca per vedere la risposta

Per componenti multi-root, gli attrs non vengono auto-ereditati su un singolo root. Gestirli esplicitamente con $attrs e opzionalmente inheritAttrs: false.

<template>
<div v-bind="$attrs">Root A</div>
<div>Root B</div>
</template>

Domanda 4: Fragment in Vue vs React

Clicca per vedere la risposta

Vue utilizza il comportamento fragment implicito nei template. React richiede una sintassi fragment esplicita (<>...</> o <Fragment>).

Domanda 5: esempio di implementazione Suspense

Clicca per vedere la risposta
<template>
<Suspense>
<template #default>
<AsyncUserProfile :userId="userId" />
</template>
<template #fallback>
<div class="loading">
<Spinner />
<p>Caricamento profilo utente...</p>
</div>
</template>
</Suspense>
</template>

<script setup>
import { ref, defineAsyncComponent } from 'vue';
import Spinner from './Spinner.vue';

const userId = ref(1);
const AsyncUserProfile = defineAsyncComponent(() =>
import('./UserProfile.vue')
);
</script>

7. Best Practices (Buone Pratiche)

Buone pratiche

Raccomandato

<!-- 1) Usare Teleport per overlay -->
<Teleport to="body">
<Modal v-if="showModal" />
</Teleport>

<!-- 2) Mantenere template multi-root semantici dove appropriato -->
<template>
<header>...</header>
<main>...</main>
<footer>...</footer>
</template>

<!-- 3) Avvolgere le parti asincrone con Suspense -->
<Suspense>
<AsyncComponent />
<template #fallback>
<LoadingSpinner />
</template>
</Suspense>

<!-- 4) Usare nomi espliciti per v-model multipli -->
<CustomForm v-model:username="username" v-model:email="email" />

Da evitare

<!-- 1) Non abusare di Teleport per contenuto regolare -->
<Teleport to="body">
<div>Contenuto normale</div>
</Teleport>

<!-- 2) Non usare multi-root solo per stile; mantenere raggruppamento logico -->
<template>
<h1>Titolo</h1>
<p>Contenuto</p>
</template>

<!-- 3) Non ignorare la gestione di errori/caricamento asincrono -->
<Suspense>
<AsyncComponent />
</Suspense>

8. Riepilogo per i Colloqui

Riepilogo per i colloqui

Promemoria rapido

Funzionalità chiave di Vue 3:

  • Composition API
  • Teleport
  • Fragment
  • Suspense
  • v-model multipli

Risposta esempio

D: Quali sono le principali funzionalità di Vue 3?

Composition API per una migliore organizzazione e riutilizzo della logica, Teleport per il rendering di overlay fuori dai container DOM locali, Fragment per nodi root multipli, Suspense per stati di caricamento asincrono, binding v-model multipli, e miglioramenti più forti di TypeScript/prestazioni.

D: Qual è un caso d'uso pratico di Teleport?

Rendering di modal/overlay nel body per evitare problemi di clipping e stacking, mantenendo la logica del modal all'interno dell'albero dei componenti originale.

Riferimenti