Vue.js

De EduTech Wiki
Aller à la navigation Aller à la recherche

Introduction

Vue.js est une bibliothèque JavaScript qui facilite la création d'interfaces utilisateur côté client dans les pages/applications web. Contrairement à d'autres bibliothèques de ce type (e.g. Angular, React, ...), Vue.js adopte une approche progressive qui peut être plus convenable à des développeurs débutant/intermédiaires. Sa caractéristique principale en ce sens consiste à fournir des mécanismes de "binding" entre les éléments HTML qui composent le DOM de la page et le code JavaScript qui modifie ces éléments, souvent suite à des interactions de l'utilisateur.

Note sur la version

Cette page se réfère à la version 2.x de la bibliothèque (voir Versionnage sémantique)

Prérequis

L'utilisation de Vue.js nécessite une bonne compétence en JavaScript, voir :

La bibliothèque ne dépend pas d'autres bibliothèques, mais peut être facilement intégrée, par exemple avec jQuery.

Une bonne connaissance en CSS est également nécessaire. Dans certains exemples présentés dans cette page le framework CSS Bootstrap est utilisé pour la mise en page, mais son utilisation n'est pas indispensable.

Comparaison avec vanilla JavaScript

À travers des extensions du langage HTML ou directement par la création de composantes (en anglais components), Vue.js permet de surmonter certaines difficultés qu'on peut rencontrer en utilisant du vanilla JavaScript ou une bibliothèque comme jQuery, notamment en ce qui concerne la mise à jour du DOM après le déclenchement d'un événement. Considérez ce simple exemple en vanilla JavaScript qui met à jour un compteur lorsqu'on clique sur un bouton.

Code HTML (seulement du body)
<h1>Client Side JavaScript</h1>
<p><button id="add">Click here to increment the count</button><span id="output">0</span></p>
Code JavaScript
var count = 0;
var btnAdd = document.getElementById("add");
var output = document.getElementById("output");

btnAdd.onclick = function () {
  count++;
  output.innerHTML = count;
}

Vous pouvez voir dans le code JavaScript que lorsqu'on a mis à jour le compteur avec count++, il est nécessaire de mettre à jour le contenu du noeud HTML (i.e. le span avec id="output") pour qu'on puisse établir une correspondance entre :

  • La valeur de la variable count telle qu'elle existe dans la logique du code JavaScript
  • La valeur de cette variable qui est affichée à l'utilisateur à travers output.innerHTML

Voici le même exemple en utilisant Vue.js (attention: il faut inclure la bibliothèque, voir plus bas dans la page).

Code HTML (seulement du body)
<h1>Simple counter with Vue.js</h1>
<div id="counter">
  <button v-on:click="increment">Click me many times!</button> Number of click: <strong>{{ count }}</strong>
</div>
Code JavaScript
var counter = new Vue({
  el: '#counter',
  data: {
    count: 0
  },
  methods: {
    increment: function() {
      this.count++;
    }
  }
});

Les éléments à remarquer dans le code HTML sont principalement deux :

  • La notation v-on:click qui est associée à la méthode increment dans le code JavaScript
  • La notation {{ count }} qui est associée de manière automatique à la valeur de la propriété data.count dans le code JavaScript

Installation

Comme toute bibliothèque JavaScript côté-client, Vue.js peut être installée tout simplement en incorporant le fichier .js dans la page HTML qui l'utilise. Pour ce faire vous pouvez :

  1. Télécharger la dernière version (2.x au moment de l'écriture de cette page, mars 2017) depuis le site officiel
  2. Utilisez le lien à une CDN
  3. Pour niveau intermédiaire/expert: Installez et utiliser une extension en ligne de commande vue-cli (nécessite installation de Node.js)

Fichier téléchargé

Téléchargez vos fichiers depuis le site officiel.

Veillez à bien utiliser la version Development version pendant le développement car elle propose des messages d'erreurs dans la console qui peuvent vous aider à éviter des fautes dans l'utilisation de la bibliothèque :

<script src="path/to/your/local/file/vue.js"></script>

Lorsque vous avez terminé le développement, vous pouvez passer à la version minified de la bibliothèque :

<script src="path/to/your/local/file/vue.min.js"></script>

CDN

Le site officiel vous conseille d'utiliser la Content Delivery Network unpkg qui propose la dernière version de la bibliothèque :

<script src="https://unpkg.com/vue/"></script>

En alternative vous pouvez choisir une version spécifique, par exemple :

<script src="https://unpkg.com/vue@2.2.6/dist/vue.min.js"></script>

Extension en ligne de commande

Pour intermédiaires/experts: cette option nécessite l'installation dans votre système de Node.js et une certaine familiarité avec l'installation/utilisation des modules Node ainsi que la ligne de commande.

Commande pour installation global du module :

npm install -g vue-cli

Ensuite vous pouvez utiliser la commande vue dans votre ligne de commande pour créer des squelettes de projets qui utilisent Vue.js. Par exemple cette commande :

vue simple my-simple-vue-app

crée un dossier my-simple-vue-app dans la position actuelle de votre ligne de commande avec un simple fichier index.html avec une simple mise en place de la bibliothèque que vous pouvez ensuite modifier.

Il existe des configurations plus complexes et puissantes mais qui ne sont pas abordées dans cette page, voir la page du projet sur GitHub pour plus d'information.

Utilisation de la bibliothèque

Vue.js peut être adopté de manière progressive, c'est-à-dire qu'on peut l'utiliser très facilement pour un projet simple, mais également pour des applications plus complexes. Le guide officiel est, pour une fois, très bien organisée, donc dans cette page nous nous limitons à un aperçu des principales caractéristiques et au fonctionnement de la bibliothèque.

Fonctionnement de base

La "magie" de Vue.js se fait à travers l'objet JavaScript new Vue() qui est mis à disposition par la bibliothèque. Cet objet (i.e. il s'agit d'un object constructeur) accepte différents paramètres, sous forme d'un objet normal JavaSscript :

var appVueJS = new Vue({
  //Spécification de l'objet de configuration
});

L'objet de configuration peut contenir plusieurs associations clé-valeurs. Ici de suite nous proposons les éléments nécessaires pour un exemple basique :

  1. La propriété el qui identifie l'élément HTML "conteneur" (e.g. #myVueDiv)
  2. La propriété data qui est associée un autre objet avec les associations clés-valeurs des propriétés/données à utiliser dans l'application
  3. La propriété methods qui est associée à un autre objet avec les associations clés-valeurs des méthodes/fonctions à utiliser dans l'application
var appVueJS = new Vue({
  //Identify the element
  el: '#myAppContainer',
  //Provide data model
  data: {
    course: "STIC I",
    credits: 6,
    exercices: [1, 2, 3, 4, 5, 6]
  },
  //Define methods/functions
  methods: {
    printName: function () {
       console.log(this.course);
    },
    goToEduTechWiki: function () {
       window.location = "https://edutechwiki.unige.ch"
    }
  }
});

Ensuite, les données et méthodes déclarée au niveau du code JavaScript peuvent être intégrées dans le code HTML de la page à travers une extension du langage HTML de base, c'est-à-dire à travers :

  • Une notation spécifique telle que la notation déclarative {{ ... }}
  • Des attributs qui peuvent être ajouté aux éléments HTML comme par exemple v-if, v-for, v-on:clik, etc.

L'importance d'identifier l'élément HTML qui détermine le scope de l'application

Parmi les éléments qui composent l'objet de configuration, celui auquel il faut prêter une attention particulière est la propriété el qui identifie l'élément dans le code HTML. Vous pouvez décider quel élément dans votre page aura la fonction de conteneur, mais il faut en tout cas éviter d'utiliser les balises html ou body et utiliser plutôt, par exemple, une balise div. Cet élément représentera par la suite le scope, c'est-à-dire le conteneur à l'intérieur duquel s'appliquent les data et les methods déclarés. Voici un exemple qui illustre ce mécanisme.

Code HTML :

<h1>Element/Scope application of Vue.js</h1>
<ul>
  <li id="app1">{{ message }}</li>
  <li id="app2">{{ message }}</li>
  <li id="no-app">{{ message }}</li>
</ul>

Code JavaScript :

var app1 = new Vue({
  el: '#app1',
  data: {
    message: 'My message for the first element with id app1'
  }
});

var app2 = new Vue({
  el: '#app2',
  data: {
    message: 'I will apply to another scope, that is the app2 element'
  }
});

Le contenu de la liste non ordonnée qui s'affiche à l'utilisateur sera le suivant :

  • My message for the first element with id app1
  • I will apply to another scope, that is the app2 element
  • {{ message }}

Ceci en raison du fait que la valeur de la variable message s'applique exclusivement à l'intérieur de l'élément identifié par la propriété el. Étant donné que le troisième li n'est pas identifié en tant qu'élément conteneur par un objet new Vue(), la notation {{ message }} n'est pas interprétée.

Le rendering dans le code HTML

Comme on l'a vu plus haut avec la notation {{ ... }}, Vue.js permet de modifier le contenu du code HTML après que le code source a été téléchargé par le navigateur. Cette possibilité peut s'appliquer à tous les éléments HTML d'une page à condition qu'ils se trouve à l'intérieur d'un élément "conteneur" identifié par Vue.js en tant que scope (voir point précédent). Ce mécanisme de rendering est par contre différent selon quel type de contenu des éléments HTML on veut modifier.

Modification du contenu d'un noeud

Si on veut modifier le contenu d'un nœud HTML, comme par exemple le texte d'un paragraphe, alors il faut utiliser la notation {{ ... }}.

<p>{{ message }}</p>

La notation {{ ... }} peut également évaluer (avec des limitations) du code JavaScript, donc on peut par exemple imaginer de transformer le texte en majuscules :

<p>{{ message.toUpperCase() }}</p>

Modification d'attributs d'un noeud

Au contraire, si on veut récupérer de manière dynamique le contenu d'un attribut d'un élément HTML, il faut plutôt utiliser la notation v-bind:attribut comme par exemple :

<img v-bind:title="message">

Dans ce cas si vous passez sur l'image avec la souris pour déclencher l'attribut HTML title, vous ne verrez pas s'afficher "message" mais plutôt la valeur associé à la propriété data.message dans votre code JavaScript.

Double binding

Une autre caractéristique très utile de Vue.js est la possibilité de créer un "double binding" entre les données du code JavaScript et l'affichage dans la page HTML. Cela se traduit par le fait que :

  • Si la valeur d'une donnée change au niveau du code, son affichage dans la page HTML se met à jour automatiquement
  • Si la valeur d'une donnée est modifiée à travers un élément interactif de la page HTML (e.g. un input), elle sera mise à jour automatiquement dans le code (et par conséquent également dans d'autres endroits de la page qui font référence à cette donnée)

Voici un exemple qui illustre ce principe.

Code HTML
<div class="container-fluid" id="app">
  <h1>Double binding with Vue.js</h1>
  <hr>
  <h2>Shout box</h2>
  <div class="form-group">
    <label>What do you want to shout?</label>
    <input class="form-control input-lg" v-model="shout">
  </div>
  <h3>You are shouting: {{ shout.toUpperCase() }}</h3>
  <hr>
  <h2>Addition</h2>
  <input v-model.number="firstNumber" type="number"> + <input v-model.number="secondNumber" type="number"> = {{ firstNumber + secondNumber }}
</div>
Code JavaScript
new Vue({
  el: '#app',
  data: {
    shout: '',
    firstNumber: 100,
    secondNumber: 50
  }
});

À travers l'attribut v-model="donnée"> on peut très facilement relier de manière bidirectionnelle du contenu modifié par l'action d'un utilisateur avec le modèle des données tel qu'il est déterminé dans le code.

Veuillez noter que dans le cas de l'addition, on peut spécifier v-model.number pour être sûr que le contenu de l'input soit traité en tant que Number() et pas String() pour éviter d'obtenir "100" + "50" = "10050".

Évenements/Actions utilisateur

Vue.js met à disposition une syntaxe pour créer/associer des gestionnaires d'événements directement aux éléments HTML de la page à travers des attributs tels que :

  • v-on:click="gestionnaire"
  • v-on:sumbmit="gestionnaire"

Ces attributs peuvent être définis d'avantage à travers des ajouts, par exemple :

  • v-on:submit.prevent="gestionnaire" peut être utilisé en association avec un form pour éviter que la soumission du formulaire recharge la page
  • v-on:key.enter="gestionnaire" répond à la touche enter du clavier

On peut ensuite associer ces événements à :

  • Directement du code JavaScript (déconseillé si ce n'est pour des manipulations très simples)
  • À une méthode déclarée dans l'objet new Vue()

Utiliser directement du code JavaScript

On peut associer à un événement directement du code JavaScript à évaluer, ce qui peut être utile surtout pour des manipulations simples, comme par exemple modifier la valeur d'une variable :

<button v-on:click="counter++">Increment</button> | <button v-on:click="counter = 0">Reset</button>

Utiliser une méthode déclarée dans l'objet new Vue()

Pour des gestionnaire plus complexes, on peut utiliser des méthodes définies à l'intérieur de la configuration de l'objet new Vue() associé au scope de l'élément. Voici un exemple.

Code HTML
<div class="container-fluid" id="app">
  <h1>Events/Actions in Vue.js</h1>
  <hr>
  <h2>2. Form submission</h2>
  <form v-on:submit.prevent="check">
    <div class="form-group">
      <label>Vue.js is a framework written in?</label>
      <input v-model="answer" required class="form-control">
    </div>
    <button type="submit" class="btn btn-primary">Check</button>
  </form>
</div>
Code JavaScript
new Vue({
  el: '#app',
  data: {
    answer: ''
  },
  methods: {
    check: function () {
      if (this.answer.toLowerCase() === 'javascript') {
        alert("Yes!");
      } else {
        alert("Nope, try again!")
      }
    }
  }
});

Dans cet exemple la méthode/fonction check() est associée à l'événement v-on:submit.prevent du formulaire.

Dans le gestionnaire d'événement on peut également passer un ou plusieurs arguments, à l'occurrence :

<button v-on:click="doSomething('with this argument')">Do something</button>

Faites attention dans ce cas à ne pas mélanger les guillemets de l'attribut HTML avec des valeurs passées en argument.

Boucles et structure de contrôle

Vue.js permet ensuite d'intégrer des boucles et de structures de contrôle directement au niveau de l'affichage HTML, ce qui facilite énormément le codage et la mise à jour du DOM par rapport au vanilla JavaScript (e.g. document.createElement() etc.). L'intégration se fait tout simplement en utilisant des attributs dans les éléments HTML qui se trouve à l'intérieur d'un scope Vue.js. Voici un exemple.

Code HTML
<div class="container-fluid" id="app">
  <h1>Loops and conditionals in Vue.js</h1>
  <hr>
  <h2>List of grades:</h2>
  <ul>
    <li v-for="item in grades">
      {{ item.course}} : {{ item.grade }} <span class="font-weight-bold text-danger" v-if="item.grade < 4">Failed!</span>
    </li>
  </ul>
</div>
Code JavaScript
new Vue({
  el: '#app',
  data: {
    grades: [
      {
        course: 'STIC I',
        grade: 5.5
      }, {
        course: 'STIC II',
        grade: 3.75
      }, {
        course: 'ERGO I',
        grade: 6
      }, {
        course: 'ERGO II',
        grade: 3.5
      }
    ]
  }
});

Grâce à la notation v-for="item in grades" associé à l'élément li on peut facilement créer une itération de tous les éléments de l'array d'objet grades. À l'intérieur de chaque itération, on utilise la notation v-if="item.grade < 4" pour déterminer si la note obtenue doit être accompagnée (ou pas) d'un menaçant "Failed!".

Techniques avancées

Valeurs computées

Parfois il est utile de créer des données qui sont déterminées par les valeurs d'autres données. Si on prend l'exemple précédent de la liste de notes, on peut imaginer d'afficher la moyenne des cours. Dans ce cas, on peut utiliser la propriété computed dans notre objet Vue.js.

Code HTML
<div class="container-fluid" id="app">
  <h1>Computed value in Vue.js</h1>
  <hr>
  <h2>List of grades:</h2>
  <ul>
    <li v-for="(item, index) in grades">
      {{ item.course}} : {{ item.grade }} <span class="font-weight-bold text-danger" v-if="item.grade < 4">Failed!</span> <button class="btn btn-default btn-sm" v-on:click="removeGrade(index)" v-if="grades.length > 1">X</button>
    </li>
  </ul>
  <h4>Your mean is {{ mean }}</h4>
  <p>Add a new grade</p>
  Course: <input v-model="newCourse"> Grade: <input v-model.number="newGrade" type="number" min="0" max="6" step="0.25"> <button class="btn btn-primary" v-on:click="addGrade">Add grade</button>
</div>
CodeJavaScript
new Vue({
  el: '#app',
  data: {
    grades: [{
      course: 'STIC I',
      grade: 5.5
    }, {
      course: 'STIC II',
      grade: 3.75
    }, {
      course: 'ERGO I',
      grade: 6
    }, {
      course: 'ERGO II',
      grade: 3.5
    }],
    newCourse: '',
    newGrade: ''
  },
  computed: {
    mean: function() {
      var sum = this.grades
        .map(function(item) {
          return item.grade;
        })
        .reduce(function(a, b) {
          return a + b;
        });
      return (sum / this.grades.length).toFixed(2);
    }
  },
  methods: {
    addGrade: function () {
      this.grades.push({
        course: this.newCourse,
        grade: this.newGrade
      });
      this.newCourse = '';
      this.newGrade = '';
    },
    removeGrade: function (index) {
      console.log(index);
      this.grades.splice(index, 1);
    }
  }
});

Par rapport à l'exemple précédent, nous avons ajouté la propriété computed qui contient la clé mean. Cette clé se caractérise par rapport à celles contenu dans data parce qu'elle est une méthode (i.e. une fonction). En effet, Vue.js appelle automatiquement cette fonction pour que la moyenne se mette à jour chaque fois qu'on ajoute une nouvelle note (à travers methods.addGrade ou methods.removeGrade).

Veuillez faire attention au fait que lorsqu'on se réfère à des données dans les valeurs computées ou dans les méthodes, il faut utiliser la notation this.nameOfTheProperty.

Composantes

Vue.js permet également de créer des composantes (components en anglais). Il s'agit de bout de code qui peuvent être réutilisés à travers des balises définies directement par le développeurs, par exemple :

<div id="app">
  <my-stic-component></my-stic-component>
</div>

Dans ce cas, on peut définir à quoi correspond la balise <my-stic-component> à travers la notation suivante :

//Fichier JavaScript
Vue.component('my-stic-component', {
  //Caractéristiques du component
});

Pour utiliser un component il faut :

  1. L'utiliser à l'intérieur d'une "application" Vue.js, c'est-à-dire à l'intérieur d'un élément HTML qui est défini en tant que scope pour l'objet new Vue()
  2. Déclarer le component avant l'application/élément scope

Pour compléter l'exemple :

Code HTML
<div id="app">
  <my-stic-component></my-stic-component>
  <p>Just a dummy paragraph</p>
</div>
Code JavaScript
//Avant définir le component
Vue.component('my-stic-component', {
  template: '<h1>Welcome to STIC!</h1>'
});

//Définir l'application/élément scope
new Vue({
  el: '#app'
});

À ce moment, la balise my-stic-component sera remplacée par le contenu du template défini dans Vue.component('my-stic-component', ...), c'est-à-dire avec un titre de premier niveau Welcome to STIC.

On peut utiliser les components de manières bien plus complexes :

  • On peut passer de l'information de l'application au component, par exemple pour créer des éléments qui se répètent dans la page
  • On peut passer de l'information du component à l'application à travers un système de gestion des événements

Pour plus d'information, voir la documentation officielle

Intégration avec autre code JavaScript

On peut également interagir avec les données et méthodes d'une application/élément scope de Vue.js à travers d'autres bouts de code JavaScript. En effet, Vue.js "expose" les objets new Vue() de manière trasparente. Par exemple :

Code HTML
<div id="app">
  <p>Message: {{ message }}</p>
  <p>Source: {{ source }}</p>
</div>
<hr>
<button id="outsideBtn">Button outside Vue.js element</button>
Code JavaScript
//Define Vue.js application/element scope
var myVue = new Vue({
  el: '#app',
  data: {
    message: 'Vue.js message',
    source: 'Vue.js object'
  },
  methods: {
    changeMessage: function () {
      this.message = 'The message has been changed'
    }
  }
});

//Use a button outside Vue.js element
var outSideButton = document.getElementById('outsideBtn');
outSideButton.addEventListener('click', function () {
  myVue.changeMessage();
  myVue.$data.source = 'JavaScript button';
});

Pour pouvoir avoir accès à l'objet new Vue() il faut d'abord l'associer à une variable et ensuite utiliser cette variable pour accéder aux éléments internes. On peut par exemple:

  • Accéder aux données à travers la notation variableName.$data.propertyName
  • Accéder aux méthodes à travers la notation variableName.methodName

Il est également possible d'accéder à d'autres éléments. Voir la documentation officielle pour plus de détails.

Liens