Web App in VueJs – Evitiamo di Perderci

W

Cos’è il routing

Come descritto nel seguente articolo: “il routing è una parte fondamentale di una qualunque applicazione front-end che si possa definire tale. Grazie a esso è possibile manovrare un’applicazione in esecuzione attraverso la richiesta di specifici path nell’url. È il cuore di ogni “Single Page App” che si rispetti.” Scopriamola in Vue.

Routing in vuejs

Oggi andremo quindi a vedere come fare per utilizzarlo al meglio all’interno della nostra applicazione web.
Nel caso non abbiate ancora un progetto VueJs, potete vedere come impostarne uno nuovo da zero, leggendo questo articolo nel quale mostro come installare vue-router oppure clonare la mia repository.

Configuriamo vue-router

Il modulo, come già detto, potete vedere come installarlo tramite vue-cli su VueJS Quickstart con Vue-cli e Vue-router.
Apriamo il file index.js che troviamo nel percorso src/router, all’interono dovremmo trovare questo codice:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})

Importando la classe principale di vue, possiamo informare l’applicazione di quali siano le nostre route tramite Vue.use(Router).
In questo modo abbiamo passato alla nostra applicazione un oggetto contenente tutte le possibili “manovre” che può effettuare.
Come possiamo vedere dal codice, ogni route ha un path che viene usato per definire una “rotta”, un nome che identifica il componente associato (opzionale) e il componente che verrà chiamato.

Modifichiamo il componente HelloWorld in questo modo:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>Nazioni</h2>
    <ul>
      <li v-for="country in countries"><router-link :to="country.url">{{ country.name }}</router-link></li>
    </ul>
    <div>
      <input type="text" v-model="text">
    </div>
    <b>two-way data binding:</b> <span v-text="text"></span>
    <button v-on:click="clearMessage">Pulisci testo</button>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App',
      countries: [
        {name: 'England', url: '/england'},
        {name: 'Spain', url: '/spain/by_hello_world'}
      ],
      text: ''
    }
  },
  methods: {
    clearMessage: function () {
      if (this.text !== '') {
        this.text = ''
      } else {
        alert('nessun testo da cancellare')
      }
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

Adesso creiamo altri 3 componenti spostandoci nella cartella components e chiamiamoli EnglandLondon e Spain. Questi avranno il seguente codice:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>England</h2>
    <ul>
      <li v-for="country in countries"><router-link :to="country.url">{{ country.name }}</router-link></li>
    </ul>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'England',
  data () {
    return {
      msg: 'Welcome to England',
      countries: [
        {name: 'Home', url: '/'},
        {name: 'Spain', url: '/spain/by_england'}
        {name: 'London', url: '/england/london'}
      ]
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>London</h2>
    <h3 v-on:click="goBack()">Go Back</h3>
  </div>
</template>

<script>
export default {
  name: 'London',
  data () {
    return {
      msg: 'Welcome to London'
    }
  },
  methods: {
    goBack () {
      window.history.length > 1
        ? this.$router.go(-1)
        : this.$router.push('/')
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>Spain</h2>
    <h3>Parameter id defined in vue router: {{ $route.params.id }}</h3>
    <ul>
      <li v-for="country in countries"><router-link :to="country.url">{{ country.name }}</router-link></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'Spain',
  data () {
    return {
      msg: 'Welcome to Spain',
      countries: [
        {name: 'Home', url: '/'},
        {name: 'England', url: '/england'}
      ]
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

Aggiungiamo due nuove routes all’interno del file index.js che si trova dentro la cartella router nel seguente modo:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import England from '@/components/England'
import London from '@/components/London'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/england',
      name: 'England',
      component: England,
      children: [
        {
          path: 'london',
          name: 'London',
          component: London
        }
      ]
    },
    { path: '/spain/:id',
      name: 'spain',
      component: Spain
    },
    {path: '/france', redirect: '/england'}
  ]
})

Così abbiamo definito tre nuove regole di routing il children, la sintassi :id e il redirect.

Children

Come potete vedere abbiamo inserito il tag router-view all’interno del template di England, questo ci permette di renderizzare i componenti figli al suo interno. Infatti se lanciamo l’applicazione tramite npm start cliccando su England e poi su London, possiamo notare che il template di quest’ultimo compare appena sotto.
Ora ci è possibile cliccare su “Go Back” il quale lancia la funzione che abbiamo scritto goBack(). Questa utilizzando la funzione go() del modulo vue-router, torna al precendente evento di routing, in questo caso al componente England con il risultato che London sparisce.

:id

Adesso tornando alla “homepage”, che nel nostro caso è il componente HelloWorld, cliccando su “spain” entriamo nel componente e dovremmo vedere la scritta “PARAMETER ID DEFINED IN VUE ROUTER: BY_HELLO_WORLD”. Questo è il parametro che abbiamo passato dalla homepage inserendo in quesry string in questo modo: “/spain/by_hello_world”.

Redirect

La redirect come già dice il nome, serve a reinderizzare un path in un altro diverso, nel nostro caso scrivendo nell’url “http://localhost:8080/#/france” ci possiamo accorgere che ha cambiato immediatamente il path in “http://localhost:8080/#/england” caricando così il componente England.

Per altri eventi di routing potete fare riferimento alla guida ufficiale di vue-router.

Props

È il momento di entrare in un discorso cruciale di qualsiasi app basata sui componenti, ovvero come passare dati da un componente padre a uno figlio. Con Vue corrono in nostro soccorso i props, quindi creiamo un nuovo componente child.

<template>
    <h4>{{myMessage}}</h4>
</template>

<script>
export default {
  props: ['myMessage'],
  name: 'Child',
  data () {
    return {
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h4 {
  cursor: pointer;
  font-weight: 400;
  color: blue;
}
</style>

Richiamiamolo in HelloWorld in questo modo:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>Nazioni</h2>
    <ul>
      <li v-for="country in countries"><router-link :to="country.url">{{ country.name }}</router-link></li>
    </ul>
    <div>
      <input type="text" v-model="text">
    </div>
    <b>two-way data binding:</b> <span v-text="text"></span>
    <button v-on:click="clearMessage">Pulisci testo</button>
    <child v-bind:my-message="parentMsg"></child>
  </div>
</template>

<script>
import Child from './HelloWorld/Child.vue'

export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App',
      countries: [
        {name: 'Italy', url: '/italy'},
        {name: 'England', url: '/england'},
        {name: 'Spain', url: '/spain/by_hello_world'}
      ],
      text: '',
      parentMsg: 'two-way data binding from parent to child component'
    }
  },
  components: {Child: Child},
  methods: {
    clearMessage: function () {
      if (this.text !== '') {
        this.text = ''
      } else {
        alert('nessun testo da cancellare')
      }
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

Nel nuovo componente abbiamo fatto in modo che tramite la proprietà props raccolga i dati passati dal componente padre.
Per far si HelloWorld veda il componente Child l’ho importiamo e lo dichiariamo nei “components”. Adesso possiamo inserirlo nel template facendo attenzione a questa proprietà che abbiamo inserito: “v-bind:my-message=”parentMsg”.
Come prima cosa notiamo che il props che abbiamo definito in Child è stato trasformato dove prima la lettera era maiuscola è diventata minuscola e preceduta dal simbolo “-“. La variabile che stiamo passando è “parentMsg” e cosa importante ma opzionale il “v-bind”. Quest’ultimo a ogni cambiamento della variabile nel componente padre aggiorna il dato anche nel componente figlio.

Come al solito potete trovare questo esercizio anche sul mio account github.

Con queste dritte sul routing sarete in grado di creare una web application di tutto rispetto e con un ottima gestione dei dati. Potete continuare a seguire le prossime guide che si spingeranno sempre più a fondo per comprendere a pieno questa libreria.

A proposito di me

Pasquale De Lucia

Appassionato di tecnologia, ama la programmazione, tanto da farla diventare la sua professione. Orientato al Front-End, ma non lascia indietro gli studi su Back-End e database.
Amante dello smart working.

Gli articoli più letti

Articoli recenti

Commenti recenti