Guida tutorial a Vue.js – 3° parte – collegamenti avanzati e metodi

In questo terzo articolo della guida Vue.js vedremo come è possibile cambiare istantaneamente i contenuti di una pagina web senza doverla ricaricare, grazie alla direttiva v-model ed alle proprietà computed e ai metodi.

Il trasferimento di dati tra l’istanza dell’oggetto Vue e il template HTML supporta pienamente le espressioni javascript. Facciamo un esempio, richiamando il codice utilizzato nel primo e nel secondo articolo della guida, che dovrebbe avere questo contenuto

<!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>
                <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 v-else>Siamo spiacenti, non ci sono annunci al momento</p>
                <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 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"
      }
    }
];         
    var vm = new Vue({
       el: '#main-app',
       data: {
          messaggio: 'Ciao mondo!!',
          link: 'https://www.vuejs.org',
          annunci: elenco
       }
    })
</script>
    </body>
</html>

All’interno del tag section id=”main-app” subito prima della chiusura del tag li inserisci questo codice:

<p>€ {{annuncio.acf.richiesta}} - $ {{Number(annuncio.acf.richiesta) * 1.22717}}</p>

Abbiamo inserito l’importo della richiesta in euro per ciascun annuncio immobiliare, tale importo è contenuto nell’array annunci contenuto all’interno dell’oggetto data dell’istanza Vue. Siccome sono un megalomane, accanto al valore in euro abbiamo inserito anche il valore in dollari, ma tale valore non è contenuto all’interno dell’array, devi ricavarlo moltiplicando il valore in euro per il tasso di cambio, dopo avere trasformato il valore della richiesta (attualmente una stringa di testo) in numero. Per fare questo utilizziamo questa espressione Number(annuncio.acf.richiesta) * 1.2187 all’interno delle doppie parentesi graffe. Ricarica la pagina web e vedrai che il codice javascript verrà eseguito correttamente. Da notare che viene supportata una singola espressione per ogni trasferimento di dati. Il codice che segue, ad esempio, non potrebbe funzionare

{{ if (condizione) { return messaggio } }}

.

Proprietà Computed

Utilizzare espressioni javascript all’interno delle doppie parentesi può portare ad una scarsa leggibilità. Uno dei pregi di Vue.js è proprio la leggibilità del codice, sostanzialmente composto da normali tag html con l’aggiunta di vari tipi di interpolazioni. Per non fare venire meno questa caratteristica, quando è necessario l’uso di espressioni javascript è possibile utilizzare le proprietà computed. Questo tipo di proprietà prende come riferimento le proprietà all’interno dell’oggetto Vue, applica a queste una qualche espressione javascript e restituisce una nuova proprietà, alla quale è possibile accedere normalmente con le normali interpolazioni viste fin qui. Un esempio può chiarire meglio le cose:

var vm = new Vue({
    el: '#main-app',
    data: {
        numero_1: 10,
        numero_2: 20,
    },
    computed: {
        somma: function () {
            return this.numero_1 + this.numero_2
        }                
    }
})

In questo esempio, all’interno dell’oggetto data abbiamo le proprietà numero_1 e numero_2. La proprietà somma è il risultato di una funzione che restituisce appunto la somma delle due proprietà statiche. Come si accede a tale proprietà? Con la normale sintassi dell’interpolazione di testo {{ somma }}. La cosa bella è che Vue conosce le proprietà su cui si basa la proprietà somma ed ogni volta che queste subiranno una modifica, anche la proprietà computed verrà aggiornata. D’altro canto, finchè le proprietà suddette non subiranno una modifica, il valore della proprietà computed non verrà ricalcolato perchè rimarrà memorizzato nella cache, alleggerendo il lavoro del browser.

Metodi

Lo stesso risultato al quale siamo giunti con la proprietà computed somma, può essere raggiunto con i metodi, che abbiamo già incontrato nell’articolo precedente quando abbiamo parlato della direttiva v-on. Il codice visto sopra può essere leggermente modificato così:

var vm = new Vue({
    el: '#main-app',
    data: {
        numero_1: 10,
        numero_2: 20,
    },
    methods: {
        somma: function () {
            return this.numero_1 + this.numero_2
        }                
    }
})

ed il metodo può essere richiamato all’interno delle doppie parentesi graffe in questo modo {{ somma() }}. Il risultato finale è praticamente identico, con la differenza che la funzione verrà sempre ricalcolata ad ogni rendering della pagina, anche se le proprietà numero_1 e numero_2 non avranno subito modifiche. I metodi sono particolarmente utili quando si verificano degli eventi che richiedono l’elaborazione di funzioni javascript.

Proviamo a modificare il nostro codice per fare un’esempio più concreto, ma per fare questo dobbiamo introdurre un’altra direttiva:

la direttiva v-model

Questa direttiva può essere utilizzata solo all’interno di form o di componenti, consente un collegamento bidirezionale tra dati e template. Mentre con la direttiva v-bind possiamo variare l’output sullo schermo al variare dei dati dell’oggetto Vue, con la direttiva v-model possiamo anche variare il valore delle proprietà dell’oggetto in base ai valori inseriti dall’utente sui campi di un form. In altri termini, con la direttiva v-bind i dati percorrono un’unica direzione passando dall’oggetto Vue al codice HTML, con la direttiva v-model i dati vanno dall’oggetto Vue al codice HTML e viceversa.

Torna al nostro file e subito dopo il tag section id=”main-app” inserisci questo codice:

<form method="post" action="/">
    <fieldset>
        <legend>Seleziona la tipologia di annuncio</legend>
        <input type="radio" v-model="tipologia" value="vendita"> Vendite
        <input type="radio" v-model="tipologia" value="affitto"> Affitti
    </fieldset>
</form>

Ora modifica il tag hl che avevamo creato prima da così 

<h1>{{messaggio}}</h1>

a così 

<h1>Immobili in {{tipologia}}</h1>

Cancella inoltre il tag

<a v-bind:href="link">link a vue.js</a>

Dopodiché aggiungi all’oggetto data la proprietà tipologia, sostituendolo alla proprietà messaggio, che adesso non ci serve più. Puoi anche eliminare la proprietà link per lo stesso motivo. L’oggetto data dovrebbe presentarsi così:

data: {
    tipologia: 'affitto',
    annunci: elenco
}

Ricapitolando, abbiamo inserito un form con due campi di input di tipo radio, entrambi questi campi contengono la direttiva v-model collegata alla proprietà tipologia che abbiamo appena inserito nell’oggetto data. Cliccando sui campi di input il valore della proprietà tipologia assumerà il valore corrispondente (value=”vendita” oppure value=”affitto”). Possiamo verificare in tempo reale la modifica di tale valore, perchè il tag h1 adesso contiene un’interpolazione di testo con la nuova proprietà tipologia.

Questa piccola modifica ovviamente non ci basta, vogliamo anche cambiare gli annunci visualizzati sullo schermo in base al tipo di scelta che effettuiamo.

Per prima cosa cancella la variabile “elenco” con tutto il suo contenuto; al suo posto crea la variabile affitti e la variabile vendite, come nel codice sotto:

var affitti = [
    {
        "title": {
          "rendered": "Appartamento arredato zona centro"
        },
        "acf": {
          "indirizzo": "Via Vattelappesca n. 4",
          "citta": "Venezia",
          "vani": "2",
          "mq": "80",
          "richiesta": "1500",
          "descrizione": "Appartamento arredato, 2 vani + cucina abitabile, ottimo stato",
          "immagine_1": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/venice-2451047_640.jpg",
          "immagine_2": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/venice-3057446_640.jpg",
          "immagine_3": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/venice-2928217_640.jpg",
          "tipologia": "affitto"
        }
      },
      {
      "title": {
        "rendered": "Attico ristrutturato"
      },
      "acf": {
        "indirizzo": "Via Vattelappesca n. 5",
        "citta": "Firenze",
        "vani": "3",
        "mq": "75",
        "richiesta": "1400",
        "descrizione": "Delizioso attico zona centro, completamente ristrutturato",
        "immagine_1": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/florence-2493041_640.jpg",
        "immagine_2": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/street-2921554_640.jpg",
        "immagine_3": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/dome-541170_640.jpg",
        "tipologia": "affitto"
      }
    },
    {
      "title": {
        "rendered": "Villetta in residence"
      },
      "acf": {
        "indirizzo": "Via Vattelappesca n. 6",
        "citta": "Marsala",
        "vani": "3",
        "mq": "80",
        "richiesta": "400",
        "descrizione": "Villetta in residence, superficie 80 mq, giardino e spazi esterni.",
        "immagine_1": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/interior-1026454_640.jpg",
        "immagine_2": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/marsala.jpg",
        "immagine_3": "https://www.alessandrocosta.pro/wp-content/uploads/2018/01/sicily-1191436_640.jpg",
        "tipologia": "affitto"
      }
    },
  ];

var vendite = [
    {
        "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",
          "tipologia": "vendita"
        }
    },
    {
        "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",
          "tipologia": "vendita"
        }
    },
    {
        "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",
          "tipologia": "vendita"
        }
    }
];

Adesso abbiamo due array di annunci, uno per gli affitti ed uno per le vendite, che verranno visualizzati alternativamente a seconda della scelta dell’utente. All’interno dell’oggetto data cancella la proprietà annunci, lasciando come unica proprietà quella denominata tipologia che abbiamo creato prima. Inserisci una proprietà computed come nel codice sotto:

var vm = new Vue({
    el: '#main-app',
    data: {
      tipologia: 'affitto'
    },
    computed: {
        annunci: function () {
          if (this.tipologia === 'affitto') {
            return affitti;
          } else if(this.tipologia === 'vendita') {
            return vendite
          }
        }
    },
})

Esaminiamo il codice. L’unica proprietà rimasta all’interno dell’oggetto data è la tipologia. Sai già che il valore di questa proprietà varia in base alla scelta dell’utente, grazie alla direttiva v-model. I due valori possibili sono “affitto” e “vendita”, come risulta dai due campi di input visti prima:

<input type="radio" v-model="tipologia" value="vendita"> Vendite
<input type="radio" v-model="tipologia" value="affitto"> Affitti

La proprietà annunci è diventata computed ed è legata alla proprietà tipologia, il suo valore è il risultato di una semplice funzione che valuta il valore di tipologia, se questa ha il valore della stringa di testo “affitto” assegniamo ad annunci la variabile affitti (che contiene l’array degli immobili in affitto), altrimenti assegniamo la variabile vendite. All’interno della funzione, per riferirci alla proprietà tipologia dobbiamo anteporre this. poichè ci stiamo riferendo al medesimo oggetto Vue. Se non avessimo usato this. Vue si sarebbe aspettato di trovare un’altra variabile tipologia all’interno dello script ma esterno all’oggetto Vue. A conferma di ciò, ti faccio notare che quando abbiamo scritto return affitti ci siamo riferiti ad una variabile esterna all’istanza Vue.

Ricarica la pagina web e seleziona le due tipologie, gli annunci mostrati a video varieranno di conseguenza.

Lo stesso risultato si può ottenere con un metodo, dobbiamo soltanto cambiare alcune righe di codice, sopratutto all’interno della variabile vm:

var vm = new Vue({
    el: '#main-app',
    data: {
      tipologia: 'affitto',
      annunci: affitti
    },
    methods: {
        filtra: function () {
          if (this.tipologia === 'affitto') {
            return this.annunci = affitti;
          } else if(this.tipologia === 'vendita') {
            return this.annunci = vendite
          }
        }
    },
})

Come puoi vedere, la proprietà annunci è tornata all’interno dell’oggetto data, abbiamo creato però l’oggetto methods al cui interno troviamo la funzione filtra che assegna alla proprietà annunci la variabile “affitti” o “vendite” in base al valore della proprietà tipologia. L’ultima modifica da apportare rispetto a prima riguarda la direttiva v-for, che da così v-for=”(annuncio, i) in annunci” deve diventare così v-for=”(annuncio, i) in filtra(annunci)”.
Concludiamo così il terzo articolo della guida, nel prossimo post inizieremo ad esaminare uno degli aspetti più interessanti di Vue.js: i componenti. Come al solito, se hai dubbi o vuoi aggiungere qualcosa scrivi un commento!