In questa lezione creiamo un esercizio per gestire le tabs in Vue.js. Le “tabs” sono solitamente utilizzati per creare interfacce utente con più schede, dove ogni scheda contiene un insieme di contenuti separati. Può essere utile ad esempio per organizzare e visualizzare diverse sezioni di informazioni o funzionalità all’interno di un’applicazione web.

Ci sono diverse librerie e approcci per creare tabs in Vue.js, ma vediamo un esempio di come poterli implementare usando i componenti Vue.js.

Esempio di tabs in Vue.js

In questo primo esempio creiamo un unico componente per la gestione delle tabs. Realizziamo un template, con due button che, quando cliccati, cambiano il valore di activeTab rispettivamente a 'tab1' e 'tab2'. Poi in un div insieramo due paragrafi che costituiscono il contenuto delle due tabs.

A questi paragrafi ho assegnato una direttiva :class che imposta la classe CSS 'active' in base a quale tab è attivo. In questo modo, quando activeTab è uguale a 'tab1', il primo paragrafo riceverà la classe 'active' e quindi sarà visualizzato. Allo stesso modo, quando activeTab è uguale a 'tab2', il secondo paragrafo verrà visualizzato.

<template>
    <div>
      <button @click="activeTab = 'tab1'">Mostra Tab 1</button>
      <button @click="activeTab = 'tab2'">Mostra Tab 2</button>
  
      <div class="tab-content">
        <p :class="{ active: activeTab === 'tab1' }">Contenuto Tab 1</p>
        <p :class="{ active: activeTab === 'tab2' }">Contenuto Tab 2</p>
      </div>
    </div>
  </template>
  

Corso su JavaScript

Banner Pubblicitario

Dopo nella sezione <script>, definiamo il componente Vue.js e utilizziamo la proprietà data per inizializzare activeTab con il valore 'tab1', in modo che il primo tab sia attivo di default quando la pagina viene caricata.

  <script>
  export default {
    name: 'TabsComponent',
    data() {
      return {
        activeTab: 'tab1'
      };
    }
  };
  </script>
 

Aggiungiamo poi due regole CSS per mostrare e nascondere i paragrafi che contengono il contenuto:


  <style scoped>
  .tab-content > p {
    display: none;
  }
  
  .tab-content > p.active {
    display: block;
  }
  </style>

Secondo esempio di tabs in Vue.js

In questo secondo esempio utilizziamo più componenti per realizzare le tabs.

Dapprima creiamo il componente TabItem dove inseriamo <slot></slot> che rappresenta un punto di inserimento per il contenuto del componente che viene fornito quando il componente viene utilizzato. Quando usiamo questo componente (<TabItem>), qualsiasi cosa inseriamo tra i tag <TabItem></TabItem> verrà inserito al posto dello slot <slot></slot>.

Usiamo la direttiva v-show per controllare la visibilità del <div> basandoci sul valore della prop isActive. Se isActive è true, il <div> sarà visibile; altrimenti, se è false, il <div> sarà nascosto.

TabItem

Ecco dunque come si presenta il componente TabItem.vue

<template>
  <div v-show="isActive">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    isActive: {
      type: Boolean,
      required: true,
    },
  },
};
</script>

Banner pubblicitario

TabsComponent

Contiuiamo l’esempio sulle tabs in Vue.js implementando adesso il sistema di tabs. Inseriamo innanzitutto nel template due sezioni principali:

  1. Una sezione per visualizzare le tabs, dove viene usato un ciclo v-for per iterare su ogni tab nell’array tabs. Ogni tab è rappresentata da un elemento <li> all’interno di una lista non ordinata <ul>.
  2. Una sezione per visualizzare il contenuto della tab attiva, utilizzando uno slot per inserire il contenuto della tab corrente.

Dopo nello script su data() definiamo le variabili, nel nostro caso activeTab, che tiene traccia dell’indice della tab attualmente attiva (partiamo di default dalla prima tab).

Poi inseriamo il metodo activateTab(index) che viene chiamato quando si fa clic su una tab. Questo metodo imposta l’indice della tab attiva ed emette un evento tab-clicked con l’indice della tab cliccata utilizzando this.$emit(). Questo permette ad altri componenti di reagire al clic sulla tab.

Diamo poi uno stile CSS a piacere.

Ecco dunque come si presenta il componente TabsComponent.

<template>
  <div>
    <div class="tabs">
      <ul>
        <li v-for="(tab, index) in tabs" :key="index" @click="activateTab(index)" :class="{ active: activeTab === index }">
          {{ tab }}
        </li>
      </ul>
    </div>
    <div class="tab-content">
      <slot :activeTab="activeTab"></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      activeTab: 0,
      tabs: ['tab 1', 'tab 2', 'tab 3']
    };
  },
  methods: {
    activateTab(index) {
      this.activeTab = index;
      this.$emit('tab-clicked', index); // Emetto l'evento tab-clicked con l'indice della tab cliccata
    },
  },
};
</script>
<style>
.tabs ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  border-radius: 5px;
  overflow: hidden;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

.tabs ul li {
  cursor: pointer;
  padding: 15px 20px;
  transition: background-color 0.3s ease;
}

.tabs ul li.is-active {
  background-color: #4CAF50;
  color: #fff;
}

.tabs ul li:hover {
  background-color: #E0E0E0;
}

.tab-content {
  border: 2px solid #ddd;
  padding: 20px;
}
</style>

TabsContainer

Terminiamo di realizzare le tabs in Vue.js creando il componente genitore che implementa il sistema di tabs.

Nel template di questo componente dunque inseriamo TabsComponent che rappresenta il container delle tabs. Viene passata la prop tabs che contiene l’array di tabs da visualizzare e la prop activeTab che indica quale tab è attualmente attiva. Viene anche ascoltato l’evento tab-clicked per aggiornare l’indice della tab attiva.

Poi inseriamo i componenti TabItem che rappresentano ogni singola tab. Utilizziamo un attributo dinamico :is-active per determinare se la tab è attiva o meno. Inseriamo poi il contenuto della tab direttamente all’interno del componente TabItem.

<template>
    <div id="app">
        <MessageContainer></MessageContainer>
        <TabsComponent :activeTab="activeTab" @tab-clicked="updateActiveTab">
        <TabItem :is-active="activeTab === 0">
            Contenuto tab 1
        </TabItem>
        <TabItem :is-active="activeTab === 1">
            Contenuto tab 2
        </TabItem>
        <TabItem :is-active="activeTab === 2">
            Contenuto tab 3
        </TabItem>
     
      </TabsComponent>
    </div>
</template>

<script>
import TabsComponent from './TabsComponent.vue';
import TabItem from './TabItem.vue';
import MessageContainer from './MessageContainer.vue';

export default {
    components: {
        TabsComponent,
        TabItem,
        MessageContainer,
    },
    data() {
        return {
            activeTab: 0,
        };
    },
    methods: {
        updateActiveTab(index) {
            this.activeTab = index;
        },
    },
};
</script>

Corso su JavaScript

Apportiamo alcune modifiche alle tabs in Vue.js

Possiamo migliorare ulteriormente il nostro sistema di tabs in Vue.js. Infatti potremmo popolare dinamicamente let abs attraverso un ciclo for ed utilizzando un array di oggetti come questo:

tabs: [
          { label: 'Tab 1', content: 'Contenuto della Tab 1' },
          { label: 'Tab 2', content: 'Contenuto della Tab 2' },
          { label: 'Tab 3', content: 'Contenuto della Tab 3' },
        ]

Quindi apportiamo le modifiche al componente TabsContainer, dove nel template inseriamo TabsComponent che rappresenta il container delle tabs a cui passiamo la prop tabs che contiene l’array di tabs da visualizzare.

<template>
    <div id="app">

      <TabsComponent :tabs="tabs" :activeTab="activeTab" @tab-clicked="updateActiveTab">
        <TabItem v-for="(tab, index) in tabs" :key="index" :is-active="index === activeTab">
          {{ tab.content }}
        </TabItem>
      </TabsComponent>
    </div>
  </template>
  
  <script>
  import TabsComponent from './TabsComponent.vue';
  import TabItem from './TabItem.vue';

  
  export default {
    components: {
      TabsComponent,
      TabItem,

    },
    data() {
      return {
        tabs: [
          { label: 'Tab 1', content: 'Contenuto della Tab 1' },
          { label: 'Tab 2', content: 'Contenuto della Tab 2' },
          { label: 'Tab 3', content: 'Contenuto della Tab 3' },
        ],
        activeTab: 0,
      };
    },
    methods: {
      updateActiveTab(index) {
        this.activeTab = index;
      },
    },
  };
  </script>
  
  <style>
  /* Stili globali possono essere aggiunti qui */
  </style>
  

Trasformiamo anche TabsComponent, dove inseriamo nelle props l’array di tabs da visualizzare, passato dal padre.

<template>
  <div>
    <div class="tabs">
      <ul>
        <li v-for="(tab, index) in tabs" :key="index" @click="activateTab(index)" :class="{ active: activeTab === index }">
          {{ tab.label }}
        </li>
      </ul>
    </div>
    <div class="tab-content">
      <slot :activeTab="activeTab"></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      activeTab: 0,
    };
  },
  props: {
    tabs: {
      type: Array,
      required: true,
    },
  },
  methods: {
    activateTab(index) {
      this.activeTab = index;
      this.$emit('tab-clicked', index); // Emetto l'evento tab-clicked con l'indice della tab cliccata
    },
  },
};
</script>

Conclusioni

In questa lezione abbiamo sviluppato degli esempi per le tabs in Vue.js che ci hanno fornito un’ottima base per comprendere i concetti fondamentali di Vue.js e come utilizzarli per creare interfacce utente interattive e reattive. Continuate a seguire gli articoli di questo blog per scoprire altri interessanti argomenti.

Alcuni link utili

Tutorial JavaScript

Componenti Vue.js

Option API

Composition API

Counter in Vue.js (con le due sintassi: Option API e Composition API)

Direttiva v-model

props con Option API