Components: data, template e props

26 settembre 2017

I componenti sono senza dubbio una delle funzionalità più interessanti di Vue. Essi permettono di progettare applicazioni di medie/grandi dimensioni organizzando il codice in moduli riutilizzabili e ben strutturati. Ciascun componente rappresenta una porzione di HTML arricchita da una logica di business incapsulata ed eventualmente una serie di regole CSS dedicate. Per utilizzare un componente possiamo utilizzare un custom tag (<mio-componente></mio-componente>) oppure l’attributo is (<div is="mio-componente"></div>)

Per poter utilizzare i componenti è necessario registrarli in Vue prima della creazione dell’istanza Vue principale. I componenti possono essere registrati:

  • globalmente se è necessario renderli disponibili in tutta l’applicazione;
  • localmente se vogliamo utilizzarli solo all’interno di un altro componente (per esempio un <tab-panel> potrebbe esistere solo all’interno di un <tabs>).

Per registrare un componente globalmente usiamo questa sintassi:

Vue.component('mio-componente', {
  [...] //elenco opzioni
});

mentre per una registrazione locale (in questo caso il componente sarà utilizzabile solo se direttamente figlio della root e non all’interno di altri componenti):

new Vue({
  [...],
  components: {
    'mio-componente': {
      [...] //elenco opzioni
    }
  }
});

Gran parte delle opzioni che vengono passate durante la definizione di un componente sono le stesse che abbiamo utilizzato per costruire l’istanza principale di Vue, con però alcune differenze.

L’opzione data

L’oggetto data che viene passato all’istanza di Vue è un oggetto che rappresenta il modello dati reattivo che viene reso disponibile da Vue. Utilizzando i componenti, è presente però una differenza sintattica, in quanto l’opzione non può più essere un oggetto, ma deve essere una funzione. Questo perchè, in caso di diverse istanze dello stesso componente, non possiamo permetterci che i dati vengano sovrascritti. Facciamo un esempio:

//questo è la modalità errata
Vue.component('mio-componente', {
  data: {
    name: 'Alberto',
    age: 99
  }
});

//questo è la modalità corretta
Vue.component('mio-componente', {
  data: function() {
    return {
      name: 'Alberto',
      age: 99
    };
  }
});

Utilizzando la seconda modalità, forziamo Vue a creare un nuovo modello dati ad ogni utilizzo di mio-componente.

L’opzione template

Come immaginabile, ciascun componente deve avere un template. Esistono diverse modalità di assegnazione di un template ad un componente, ciascuna con i suoi vantaggi e svantaggi. La scelta della modalità deve essere compatibile con la tipologia di applicazione e la frequenza di riutilizzo di un componente.

Template come stringa

La modalità più semplice è quella di definire il template come stringa all’interno del componente. Questa modalità ha ovviamente senso nel momento in cui l’HTML del componente è semplice e non prevede una grande quantità di nodi o di direttive.

Vue.component('mio-componente', {
  template: '<b>Io sono il corpo del componente</b>'
});
<mio-componente></mio-componente>

Template come nodo esterno

È possibile definire il template in un nodo terzo, più consono a contenere HTML, e referenziare questo nodo direttamente nel componente. Il template può essere contenuto all’interno di un tag <template> o di un tag <script> con type text/x-template. Questa modalità è ovviamente più complessa della precedente e permette di avere componenti con template di una complessità notevolmente superiore.

Vue.component('mio-componente', {
  template: '#mio-componente-template'
});
<mio-componente></mio-componente>
<template id="mio-componente-template">
  <b>Io sono il corpo del componente</b>
</template>

Template inline

La terza modalità è quella di definire un template inline all’interno del nodo stesso del componente. Questa è una modalità che permette di avere diverse istanziazioni dello stesso componente ma con template differenti. Per poter utilizzare uesta modalità è necessario l’utilizzo dell’attributo inline-template

Vue.component('mio-componente', {
  template: '#mio-componente-template'
});
<mio-componente inline-template>
  <b>Io sono il corpo del componente</b>
</mio-componente>

Single file components

Esiste una quarta modalità, ancora più complessa, che introdurremo successivamente in quanto richiede una conoscenza più approfondita dei componenti e di Vue in generale

L’opzione props

Le props rappresentano le proprietà esterne che permettono di configurare un componente. Dato che ciascun componente ha uno scope di esecuzione isolato, qualsiasi tipologia di dato esterno che deve essere reso accessibile dentro il componente, deve essere passato tramite appunto una prop. Le proprietà devono essere definite a priori tramite appunto l’opzione props. Inoltre, se necessario, è possibile definire il loro tipo (String, Boolean, Number…), l’eventuale obbligatorietà (required) o un valore di default.

Le props possono essere passate ad un componente in maniera statica o dinamica. Questo significa che una proprietà può essere un valore definito in fase di inizializazione di un componente oppure una variabile, controllabile da un componente più esterno. Ovviamente in questo secondo caso, un’eventuale modifica della variabile all’esterno del componente, produrrà una modifica anche al valore della proprietà.

Un primo esempio

È arrivato il momento di fermarci e cercare di riassumere con un esempio quanto appreso fino ad ora sui componenti. L’esempio è rappresentato da una piccola applicazione per la gestione di una anagrafica di persone (composte da nome e cognome) con la possibilità di aggiungere nuove persone alla lista.

<div id="app">
  <people-list :people="people"></people-list>
  <div>
    <input v-model="name" placeholder="name"><br/>
    <input v-model="surname" placeholder="surname"><br/>
    <button @click.prevent="addPerson">Add person</button>
  </div>
</div>

<template id="people-list">
  <div>
    <person v-for="person in people" :person="person"></person>
  </div>
</template>

<template id="person">
  <div><i>{{ person.name }}</i> <b>{{ person.surname }}</b></div>
</template>

L’HTML è composto da un div (con id app) che rappresenta il cuore dell’applicazione. All’interno di esso viene creato un componente people-list al quale viene passato il valore dell’oggetto people e viene creato un piccolo form composto da due campi (rispettivamente bindati a name e surname) e un button (bindato alla funzione addPerson). Oltre al div principale sono presenti due template, uno relativo al componente people-list e l’altro al componente person. All’interno del primo componente è presente la creazione, all’interno di un ciclo v-for, di diversi componenti person. Il secondo componente invece ha come unico scopo quello di mostrare nome e cognome della singola persona.

Vue.component('people-list', {
  template: '#people-list',
  props: ['people']
})

Vue.component('person', {
  template: '#person',
  props: ['person']
});

new Vue({
  el: '#app',
  data: {
    people: [
      { name: 'Alberto', surname: 'Bianchi' },
      { name: 'Marco', surname: 'Rossi' },
      { name: 'Luca', surname: 'Verdi' },
    ],
    name: '',
    surname: ''
  },
  methods: {
    addPerson: function() {
      this.people.push({
        name: this.name,
        surname: this.surname
      });
      this.name = '';
      this.surname = '';
    }
  }
});

All’interno del JS invece sono presenti le due definizione dei componenti descritti prima e l’istanziazione dell’oggetto Vue. Quest’ultimo oggetto presenta un array di 3 persone già inserite nella nostra anagrafiche, due stringhe (name e surname, inizialmente vuoti) associate ai campi del form e un metodo che permette di appendere all’interno dell’elenco di persone un nuovo elemento. I componenti invece non fanno altro che ricevere props esterne e di referenziare un template.

Quando un utente clicca sul pulsante, una nuova persona viene inserita all’interno della lista people. Essendo questa però associata al componente people-list tramite una prop, il click dell’utente forza anche la rivalutazione del v-for che, data la presenza di un nuovo elemento, stampa a video la nuova persona appena aggiunta tramite la form.

Tutte le lezioni

1 ... 9 10 11

Se vuoi aggiornamenti su Components: data, template e props inserisci la tua e-mail nel box qui sotto:
Tags:
 
X
Se vuoi aggiornamenti su Components: data, template e props

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy