Guida tutorial a Vue.js – 2° parte – le direttive principali

In questo secondo articolo della guida a Vue.js conoscerai le principali direttive del framework, v-for, v-if, v-else, v-show e v-on. Mentre imparerai ad apprezzarne le funzionalità, continuerai a costruire il sito web di annunci immobiliari che hai iniziato nel primo articolo della guida.

Nell’articolo precedente ci siamo concentrati sulla direttiva v-bind, che ha lo scopo consentire il trasferimento dei dati contenuti all’interno dell’oggetto data e gli attributi dei tag html che vogliamo aggiornare dinamicamente con Vue. Se hai seguito il post precedente, dovresti avere un file html con il codice riportato sotto:

<!DOCTYPE html>
<html>
    <head>
        <title>Vue Tutorial</title>
        <link rel="stylesheet" href="foundation.min.css">
        <link href="https://fonts.googleapis.com/css?family=Open+Sans|Oswald:700" rel="stylesheet">
        <link rel="stylesheet" href="style.css">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    </head>
     
    <body>
        <div class="wrapper row">
            <header class="site-header">
                    <div class="site-branding small-12 large-3 columns" id="site-branding">
                        <a href="#" title="Vue Tutorial">
                            <h1 class="site-title">Vue Tutorial</h1>
                        </a>
                        <p class="site-description">Il sito per creare con Vue.js</p>
                    </div><!-- .site-branding -->
                    <div class="site-header-menu small-12 large-9 columns">
                        <nav class="main-navigation" role="navigation" aria-label="Primary Menu">
                            <ul id="menu-primary" class="menu">
                                <li class="menu-item">
                                    <a href="#">Home</a>
                                </li>
                                <li class="menu-item">
                                    <a href="#">Chi siamo</a>
                                </li>
                                <li class="menu-item">
                                    <a href="#">Blog</a>
                                </li>
                                <li class="menu-item">
                                    <a href="#">Contatti</a>
                                </li>
                            </ul>
                        </nav><!-- .main-navigation -->
                    </div><!-- .site-header-menu -->
            </header>
            <section id="main-app">
                <h1>{{messaggio}}</h1>
                <a v-bind:href="link">link a vue.js</a>
            </section>
            <footer class="site-footer">
                <ul>
                    <li><h3>Contatti</h3></li>
                    <li>Facebook</li>
                    <li>LinkedIn</li>
                    <li>Google+</li>
                </ul>
            </footer>
        </div>
        <script>
    var vm = new Vue({
       el: '#main-app',
       data: {
          messaggio: 'Ciao mondo!!',
          link: 'https://www.vuejs.org'
       }
    })
</script>
    </body>
</html>

La direttiva v-for

La direttiva v-for ha lo scopo di visualizzare una lista di elementi contenuti in un array. Vai all’inizio del tag script e incolla il codice seguente:

var elenco = [
    {
      "title": {
        "rendered": "Monolocale da ristrutturare"
      },
      "acf": {
        "indirizzo": "Via Vattelappesca n. 3",
        "citta": "albenga",
        "vani": "1",
        "mq": "40",
        "richiesta": "50000",
        "descrizione": "Monolocale piano terra da ristrutturare",
        "immagine_1": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/albenga-673212_640.jpg",
        "immagine_2": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/albenga-673259_640.jpg",
        "immagine_3": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/centa-673151_640.jpg"
      }
    },
    {
      "title": {
        "rendered": "Trullo"
      },
      "acf": {
        "indirizzo": "Via Vattelappesca n. 2",
        "citta": "Alberobello",
        "vani": "2",
        "mq": "50",
        "richiesta": "800000",
        "descrizione": "Caratteristico ed affascinante trullo",
        "immagine_1": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/puglia-2740078_640.jpg",
        "immagine_2": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/alberobello-1816422_640.jpg",
        "immagine_3": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/house-552083_640.jpg"
      }
    },
    {
      "title": {
        "rendered": "Appartamento zona centro"
      },
      "acf": {
        "indirizzo": "Via Vattelappesca n. 1",
        "citta": "Roma",
        "vani": "5",
        "mq": "140",
        "richiesta": "900000",
        "descrizione": "Appartamento prestigioso completamente ristrutturato fronte Colosseo. Non ti accorgerai di averlo acquistato!",
        "immagine_1": "https://www.alessandrocosta.pro/wp-content/uploads/2017/12/building-2942786_1280-e1515500315125.jpg",
        "immagine_2": "https://www.alessandrocosta.pro/wp-content/uploads/2017/12/rome-2030648_640.jpg",
        "immagine_3": "https://www.alessandrocosta.pro/wp-content/uploads/2017/12/rome-2093608_640.jpg"
      }
    }
];

Si tratta di un array di oggetti in formato JSON contenente i dati degli annunci immobiliari da visualizzare. Più tardi nella guida li otterremo tramite AJAX, ma per adesso limitiamoci ad assegnarli alla variabile elenco appena dichiarata.

Aggiungiamo adesso la proprietà annunci all’oggetto data, alla quale assegniamo il valore della variabile elenco, cioè l’array di annunci immobiliari.

var vm = new Vue({
    el: '#main-app',
    data: {
        messaggio: 'Ciao Mondo!!',
        link: 'www.vuejs.org',
        annunci: elenco
    }
})

Vogliamo che questi annunci vengano visualizzati sullo schermo uno per volta in una lista, come in un ciclo for, per fare questo utilizzaremo la direttiva v-for. All’interno del tag section id=”main-pp”, sotto il tag h1, crea una lista ul ed al suo interno un solo tag li come nel codice seguente:

<section id="main-app">
    <h1>{{messaggio}}</h1>
    <ul>
        <li class="small-12 large-4 columns" v-for="(annuncio, i) in annunci" v-bind:key="i">
            <img :src="annuncio.acf.immagine_1">
            <p>{{annuncio.title.rendered}}</p>
            <p>{{annuncio.acf.indirizzo}} - {{annuncio.acf.citta}}</p>
        </li>
    </ul>
</section>

Il tag li appena digitato verrà visualizzato sulla pagina web tante volte quanti sono gli elementi dell’array annunci che abbiamo inserito tra le proprietà dell’oggetto data. La sintassi della direttiva v-for richiede fondamentalmente la forma v-for=”elemento in elementi”, dove “elementi” è l’array ed “elemento” è un segnaposto dell’elemento dell’array che viene elaborato in quel momento.  Nell’esempio sopra ho inserito un secondo argomento, opzionale, key. Tieni presente che quando una lista viene aggiornata, Vue non sposta gli elementi del DOM, li lascia al loro posto e li renderizza nuovamente con il contenuto che dovrebbero avere in quel momento, come se fossero degli adesivi da staccare ed incollare sopra dei mattoncini. Questo sistema, giustificato da una maggiore velocità di rendering della pagina, può comportare dei risultati inaspettati, sopratutto quando è necessario un riposizionamento degli elementi del DOM. Per evitare questo problema occorre utilizzare l’attributo key attraverso la direttiva v-bind. In questo modo è possibile attribuire ad ogni elemento della lista una chiave univoca, che può essere l’indice dell’elemento dell’array, come nell’esempio sopra v-bind:key=”annuncio.i”. Eventuali aggiornamenti della lista comporteranno un riposizionamento degli elementi del DOM, senza spiacevoli sorprese. Inoltre l’attributo key è obbligatorio quando la direttiva v-for è utilizzata all”interno di un componente, di cui parleremo diffusamente in seguito.

Le direttive v-if, v-else, v-else-if

Con Vue.js puoi subordinare il rendering di un tag o di interi blocchi di codice al verificarsi di una condizione, grazie alla direttiva v-if. Prova a modificare il codice del tag ul nel modo seguente:

<ul v-if="annunci.length > 0">

In questo modo il tag ul (e tutto il suo contenuto) verrà visualizzato soltanto se l’array annunci avrà una lunghezza maggiore di 0, cioè almeno un elemento. Prova a modificare il valore della proprietà annunci in questo modo: annunci: ”. Adesso, ricaricando la pagina web gli annunci sono scomparsi e se provi ad ispezionare gli elementi della pagina puoi vedere che l’intero ul non è proprio presente nella pagina.

In presenza della direttiva v-if è possibile utilizzare anche la direttiva v-else per impostare un blocco di codice alternativo da visualizzare nel caso in cui la condizione non si verifichi. Per capirci meglio, inserisci questo codice subito dopo la chiusura del tag ul:

<p v-else>Siamo spiacenti, non ci sono annunci al momento</p>

Ricarica la pagina web e vedrai apparire questo messaggio al posto degli annunci.

Adesso modifica di nuovo il valore della proprietà annunci, riportandolo alla versione precedente annunci: elenco, in questo modo il valore della condizione annunci.length > 0 sarà true e sullo schermo appariranno nuovamente gli annunci. Nel caso vi fossero diverse condizioni da verificare, è possibile utilizzare anche la direttiva v-else-if come in questo esempio:

<p v-if="condizione 1">Messaggio 1</p>
<p v-else-if="condizione 2">Messaggio 2</p>
<p v-else-if="condizione 3">Messaggio 3</p>
<p v-else-if="condizione 4">Messaggio 4>/p>
<p v-else>Messaggio standard</p>

Le direttive v-else e v-else-if funzionano esclusivamente se i tag ai quali sono applicati sono immediatamente successivi agli elementi v-if o v-else-if. Se il codice che abbiamo digitato sopra fosse così:

<ul v-if="annunci.length < 0">
   <li class="small-12 large-4 columns" v-for="(annuncio, i) in annunci" v-bind:key="i">
      <img :src="annuncio.acf.immagine_1">
      <p>{{annuncio.title.rendered}}</p>
      <p>{{annuncio.acf.indirizzo}} - {{annuncio.acf.citta}}</p>
   </li>
</ul>
<p>Scopri l'intruso</p>
<p v-else>Siamo spiacenti, non ci sono annunci al momento</p>

e la condizione non fosse vera, il blocco v-else non verrebbe comunque visualizzato.

Nell’esempio che abbiamo visto sopra la direttiva v-if è stata applicata al tag ul e la direttiva v-for al tag li. In questo modo Vue prima verifica la condizione e dopo, se la condizione è true, itera il ciclo for. Cosa sarebbe successo se avessimo applicato la direttiva v-if al tag li piuttosto che alla ul? Entrambe le direttive sarebbero state applicate allo stesso tag, ma la direttiva v-for avrebbe avuto il sopravvento, per cui Vue avrebbe comunque iterato il ciclo for, e ad ogni iterazione avrebbe verificato la sussistenza della condizione per l’elemento esaminato. Questa modalità può essere utile nel caso in cui all’interno del ciclo vi sono elementi differenti tra loro e vogliamo renderizzare solo alcuni di essi.

La direttiva v-show

Un risultato simile a quanto realizzato con la direttiva v-if si può ottenere con la direttiva v-show. Modifica il tag ul in questo modo:

<ul v-show="annunci.length < 0">

A prima vista sembra che non sia cambiato nulla, ma la differenza, anche se sottile, c’è. Prova a visualizzare il codice sorgente, vedrai che il tag ul è comunque presente all’interno del DOM, ma non sarà visibile perchè avrà applicata la proprietà css “display: none”. Con la direttiva precedente invece, se la condizione non fosse stata vera l’elemento non sarebbe stato inserito all’interno del DOM.

La direttiva v-on

La direttiva v-on ha lo scopo di attivare un metodo dell’istanza di Vue (o di un componente) al verificarsi di un determinato evento.
Supponi di avere questo codice html:

<button v-on:click="miaFunzione">clicca</button>

e nell’istanza di Vue questo metodo:

var vm = new Vue({
    el: '#main-app',
    data: {
      messaggio: 'Ciao Mondo!!',
    },
    methods: {
        miaFunzione: function(){
           console.log("il metodo funziona!")
        }
    }
})

Al verificarsi dell’evento, cioè cliccando sul bottone, Vue eseguirà la funzione ed il messaggio apparirà sulla console javascript. Tieni presente che la funzione può anche contenere un argomento, il cui valore viene passato attraverso la direttiva v-on. Cambiamo il codice che abbiamo scritto prima così:

<button v-on:click="miaFunzione('Vue.js spacca!')">clicca</button>
var vm = new Vue({
    el: '#main-app',
    data: {
      messaggio: 'Ciao Mondo!!',
    },
    methods: {
        miaFunzione: function(valore){
           console.log(valore)
        }
    }
})

In questo caso il testo da visualizzare nella console javascript non viene specificato all’interno del componente, ma viene passato come argomento della funzione miaFunzione. Ci occuperemo di eventi nel quarto capitolo della guida, mentre il prossimo articolo sarà dedicato ai collegamenti avanzati ed ai metodi, che abbiamo intravisto in queste ultime righe di codice.