Comprendre Vue.js : introduction

image_pdfimage_print

Vue.js connaît un succès de plus en plus grand. Le projet sur Github a 118621 étoiles au moment ou j’écris cette ligne. Qui aurait parié sur ce petit poucet face à React et Angular ? Vue.je est un “framework progressif”, ce qui signifie qu’on peut le mettre en œuvre de façon incrémentielle. D’autre part il s’entend très bien avec la plupart des librairies Javascript. Il devient ainsi une solution incontournable pour créer une application SPA (Single Page Application). Mais il trouve également toute sa place dans des application qui font un appel intensif au serveur…

Pour les développeurs PHP Javascript se présente toujours comme un langage un peu étrange avec des pratiques pas toujours très lisibles. Dans ce sens Vue.je, malgré sa simplicité, peut sembler parfois un peu “magique”.

Dans cette nouvelle série je voudrais démystifier Vue.js en montrant comme il sait résoudre avec élégance la plupart des traitements qui se présentent côté client.

Dans ce premier article on va voir comment mettre en place une infrastructure de développement, les outils à mettre en œuvre et les bases du codage.

Les outils

Pour utiliser Vue vous aurez besoin de Node.js, il faut donc commencer par l’installer. Vous aurez ainsi automatiquement npm qui est le gestionnaire de package de node.

Si vous ne savez pas si vous avez déjà node installé il suffit dans une console de taper :

node -v

Vous aurez ainsi le numéro de version s’il est installé. Actuellement on en est à la version 10.13.0, si votre version est un peu ancienne je vous conseille de la mettre à jour.

Vous pouvez aussi vérifier votre version de npm :

npm -v

Actuellement on en est à la version 6.4.1.

Vous pouvez alors installer Vue Cli de façon globale :

npm install -g @vue/cli

Vérifiez la bonne installation en demandant la version (attention le V est majuscule) :

vue -V

Vous pouvez voir toutes les commandes disponibles :

vue -h

Commands:

  create [options] <app-name>           create a new project powered by vue-cli-service
  add <plugin> [pluginOptions]          install a plugin and invoke its generator in an already created project
  invoke <plugin> [pluginOptions]       invoke the generator of a plugin in an already created project
  inspect [options] [paths...]          inspect the webpack config in a project with vue-cli-service
  serve [options] [entry]               serve a .js or .vue file in development mode with zero config
  build [options] [entry]               build a .js or .vue file in production mode with zero config
  ui [options]                          start and open the vue-cli ui
  init [options] <template> <app-name>  generate a project from a remote template (legacy API, requires @vue/cli-init)
  config [options] [value]              inspect and modify the config

Vue Cli est l’outil de base pour développer avec Vue.js et nous l’utiliseront tout au long de cette série.

Vous aurez aussi besoin de git. Là aussi vérifiez si vous l’avez :

git --version

Si ce n’est pa sle cas alors installez-le…

Il vous faudra aussi un éditeur. Là le choix est large ! Depuis quelques temps j’utilise pas mal Visual Studio Code que je trouve de plus en plus intéressant. On peut lui ajouter de nombreuses extensions pour Vue.js.

Enfin vous pouvez ajouter vue-devtools à votre navigateur préféré.

Voilà vous avez maintenant tous les outils !

Créer un projet avec Vue Cli

On va voir maintenant comment créer un projet avec Vue Cli. Ouvrez une console et positionnez-vous dans le dossier désiré, ensuite tapez :

vue create projet1

Choisissez les options “default” et “npm” et ensuite attendez…

Si tout se passe bien vous avez une longue liste d’informations qui se termine par :

Successfully created project projet1.
Get started with the following commands:

 $ cd projet1
 $ npm run serve

On va donc taper ces 2 lignes. La première est juste pour changer de dossier. La seconde lance un serveur de développement.

DONE  Compiled successfully in 4719ms                                                                                                                                                                  19:16:10

 App running at:
 - Local:   http://localhost:8080/
 - Network: http://192.168.0.43:8080/

 Note that the development build is not optimized.
 To create a production build, run npm run build.

En entrant l’url http://localhost:8080 dans un navigateur vous devriez obtenir ceci :

Si c’est le cas bravo ! Sinon reprenez toutes les indications depuis le début, vous avez dû rater quelque chose !

Voici l’architecture du projet :

Voyons déjà un peu les éléments principaux :

  • node_modules : toutes les dépendances nécessaires au projet chargées par npm à partir de la configuration de package.json
  • public/index.html : le fichier HTML d’entrée du projet
  • src/main.js : le fichier Javascript de configuration du projet
  • src/App.vue : composant de base de l’application. Les composants sont les pièces de construction de Vue.js et comportent du HTML, du CSS et du Javascript
  • src/components/HelloWorld.vue : encore un composant, c’est lui qui affiche la page de présentation vue ci-dessus
  • src/assets : un dossier pour les éléments statiques du projet comme les images

Le composant HelloWorld

J’ai dit que la brique de base de Vue.js est le composant. Regardons de plus près HelloWorld.vue.  On peut le décomposer en 3 parties.

Le template

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>
      For guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    ...
  </div>
</template>

Le template contient tout le HTML du composant, donc la structure du composant.

Le script

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

La c’est le moteur Javascript du composant, on reviendra sur le code.

Le style

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

Là on a le CSS du composant, donc la gestion de l’apparence. Notez au passage le commentaire qui indique d’ajouter scoped pour limiter le style au composant.

Le composant App

Si vous regardez le composant App.vue vous trouvez la même organisation en 3 parties :

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

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

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

J’ai dit plus haut que c’est le composant de base de l’application. remarquez l’id app dans le template :

<div id="app">

Ensuite on a l’affichage du logo :

<img alt="Vue logo" src="./assets/logo.png">

Et ensuite quelque chose de très intéressant avec une balise un peu spéciale :

<HelloWorld msg="Welcome to Your Vue.js App"/>

Vous ne connaissez certainement pas la balise HelloWorld, c’est la façon qu’à Vue.js pour intégrer un composant dans un template tout simplement en créant une balise avec le nom du composant. Donc ici dans le template on dit :

  • insérer le composant HelloWorld
  • lui transmettre une variable avec l’attribut msg

Dans le composant helloWorld l’affichage se fera sur cette ligne :

<h1>{{ msg }}</h1>

La syntaxe avec la double accolade est classique et a été adoptée par Vue.js.

Utiliser une balise avec le nom du composant ne suffit pas, il faut aussi charger le composant :

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

On change un peu les choses

Maintenant qu’on a compris le principe on peut changer un peu le code. Déjà dans App.vue on va supprimer le logo et changer le message :

<template>
  <div id="app">
    <HelloWorld msg="Ma première application avec Vue.js"/>
  </div>
</template>

Et pour le template de HelloWorld :

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p> C'est ici que je vais m'amuser</p>
  </div>
</template>

Ce qui nous donne :

Installer un framework CSS

Plutôt que de gérer laborieusement le CSS autant installer un framework. On a pas mal de choix alors prenons par exemple materialize que j’aime bien. Pour en disposer il faut l’ajouter avec npm :

npm i materialize-css

Vous allez ainsi l’avoir dans node_modules :

Il faut maintenant l’importer dans l’application. J’ai dit plus haut que la configuration se fait dans main.js :

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// C'est ici qu'on importe Materialize
import "materialize-css/dist/css/materialize.min.css";

new Vue({
  render: h => h(App),
}).$mount('#app')

Normalement vous allez constater la différence de style du titre :

Dans App.vue on va supprimer tout le style et juste ajouter une classe :

<template>
  <div id="app" class="center-align">
    <HelloWorld msg="Ma première application avec Vue.js"/>
  </div>
</template>

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

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</script>

On va aussi supprimer tout le style dans HelloWorld.vue :

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p> C'est ici que je vais m'amuser</p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<style scoped></style>

Maintenant pour le style on va se contenter de Materialize…

On commence à s’amuser

Maintenant on a tout ce qu’il faut pour un peu s’amuser avec Vue.js…

On va faire simple pour commencer, juste ajouter un bouton et incrémenter un compteur à chaque clic. Pour le faire on doit ajouter une variable dans le composant, on le fait en créant une propriété data :

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data: function() {
    return  {
      compteur: 0
    }
  }
}
</script>

J’ai créé ici une variable compteur initialisée à 0.

Ensuite on modifie le template pour ajouter le bouton et prévoir l’affichage de la valeur :

<template>
  <div>
    <h1>{{ msg }}</h1>
    <p> C'est ici que je vais m'amuser</p>
    <a class="waves-effect waves-light btn">On appuie ici !</a>
    <p>On va un peu compter : {{ compteur }}</p>
  </div>
</template>

Tout est prêt mais pour le moment il ne se passe rien parce qu’on a pas prévu de code pour incrémenter le compteur à chaque clic…

On va donc ajouter une méthode dans le composant :

<script>
export default {
  ...
  methods: {
    ajouter() {
      this.compteur++;
    }
  }
}
</script>

Et pour capter le clic du bouton on ajoute une directive :

<a class="waves-effect waves-light btn" v-on:click="ajouter">On appuie ici !</a>

Il existe une syntaxe alternative plus légère :

<a class="waves-effect waves-light btn" @click="ajouter">On appuie ici !</a>

Maintenant à chaque clic le compteur s’incrémente :

Voici une représentation de la succession des événements :

Vous voyez qu’il est très simple de mettre en place des données dynamiques !

Vue Devtools

Je vous ai dit plus haut d’installer vue-devtools dans votre navigateur. Voyons un peu à quoi il sert. Voici l’apparence avec Chrome :

Vous voyez que l’application Vue a été détectée et qu’on a accès aux composants et leurs propriétés.

Vous pourrez voir la variable compteur s’incrémenter à chaque clic.

Pour le moment cet outil n’est pas très utile mais il le deviendra en enrichissant le code en permettant un débogage efficace.

On continue à s’amuser

On va maintenant imaginer que le compteur a une limite, par exemple 10 et que lorsqu’on atteint cette limite le compteur se bloquer avec le bouton qui devient inactif. On va utiliser encore une directive :

<a class="waves-effect waves-light btn" v-bind:class="{ disabled: max }" @click="ajouter">On appuie ici !</a>

On établie un lien (v-bind) entre l’attribut class pour la classe disabled qui dépend de la variable max. Si cette variable est false rien ne se passe mais si elle est true disabled est activé et le bouton devient inactif.

On peut simplifier la syntaxe ainsi :

:class="{ disabled: max }"

On ajoute donc cette variable au composant :

data: function() {
  return  {
    compteur: 0,
    max: false
  }
},

Et on modifie la méthode ajouter pour le traitement :

methods: {
  ajouter() {
    if(this.compteur < 10) {
      this.compteur++;
    } else {
      this.max = true;
    }      
  }
}

Maintenant quand on arrive à 10 le compteur se bloque et le bouton est inactif :

On peut schématiser ainsi :

On voit qu’il est ainsi très facile de modifier une classe, ou plusieurs comme nous le verrons dans un autre article.

Ce qui serait bien maintenant serait d’afficher un message pour prévenir que le nombre maximal est atteint.

On va utiliser la directive v-if qui permet de rendre un rendu conditionnel :

<template>
  <div>
    ...
    <p>On va un peu compter : {{ compteur }}</p>
    <div v-if="max" class="row">
      <div class="col s4 offset-s4">
        <div class="card-panel red"><span class="white-text">Vous avez atteint le maximum !</span></div>
      </div>
    </div>
  </div>
</template>

On voit cette syntaxe :

v-if="max"

Donc on fera apparaître le contenu de cette balise div uniquement si la variable max est true, donc lorsqu’on arrive à 10 :

Vous voyez qu’il est très facile de jouer avec Vue.js !

La communication entre les composants

On a vu qu’on a deux composants :

  • App.vue : le composant principal
  • HelloWorld.vue : un composant enfant

Les composants dans Vue.js sont bien isolés pour éviter le mélange de données. Mais il faut aussi qu’ils puissent communiquer. Dans le sens parent->enfant ça se fait avec des props. Si vous regardez le code de HelloWorld vous trouvez cette partie :

export default {
  ...
  props: {
    msg: String
  },

Ce qui signifie que le composant attend qu’on lui transmette une valeur pour la variable msg. Ce que fait le composant parent App lorsqu’il déclare le composant enfant :

<HelloWorld msg="Ma première application avec Vue.js"/>

On précise le type de donnée qu’on désire. Si un mauvais type est transmis on aura une erreur dans la console du navigateur. Par exemple si je change le type pour Array  :

On verra plus tard comment s’effectue la communication dans l’autre sens, donc de l’enfant vers le parent à partir d’événements.

Conclusion

Dans ce premier article on a vu comment mettre en place tous les outils pour jouer avec Vue.js. On a aussi utilisé Vue Cli pour créer un projet. On a vu comment est structuré un composant et on a commencé à utiliser Vue pour créer un simple compteur incrémenté par un bouton. On a ensuite ajouté certaines fonctionnalités comme une limite au compteur et l’apparition d’un message conditionnel.

Dans le prochain article on continuera cette exploration de Vue.

Laisser un commentaire