Apprendre Vue.js 3 - : concepts de base

Remarque

Ce tutoriel est plus un récapitulatif des possibilités de Vue js. Pour un cours plus complet vous pouvez aller à cette adresse : https://v3.vuejs.org/guide/introduction.html

Qu’est-ce que Vue.js ?

Vue.js est un framework progressif pour JavaScript utilisé pour créer des interfaces Web et des applications d'une page (SPA). Vue.js peut également être utilisé pour le développement d'applications de bureau et mobiles avec les frameworks Ionic et Electron.

Pourquoi Vue.js

Avant d’utiliser un framework il est important de comprendre dans quel contexte il s’avère le bon outil.

Voici donc la liste des différentes raisons qui pourraient justifier l’utilisation d’un framework comme Vue.js

Extensions VisualStudioCode pour être productif avec Vue

Comment Utiliser/installer Vue.js

Vue est un framework dit progressif. Vous pouvez l’utiliser juste dans une petite partie de votre page web ou si vous préférez vous pouvez construire une application entière avec Vue.js.

Il y a 4 possibilités "d'installer" vue js dans vos applications :

1.     Importez-le en tant que package CDN sur la page (ce sera la solution choisie ici).

  1. Téléchargez les fichiers JavaScript et hébergez-les vous-même.
  2. Installez-le en utilisant npm.
  3. Vue fournit une CLI officielle (ouvre une nouvelle fenêtre) pour un échafaudage rapide d'applications monopages ambitieuses.

La CLI suppose une connaissance préalable de Node.js et des outils de génération associés. Nous allons donc utiliser vue js avec un lien CDN dans un 1er temps. Nous utiliserons l'outil CLI dans un 2nd temps.

Voici ce que l'on fera pour utiliser Vue seulement dans une partie de notre page web :

·        Ajouter un tag 'script' qui contient un lien vers la librairie Vue.js


 

Remarque :

Quel que soit le navigateur utilisé, il est impératif durant la phase de développement, d'afficher la console web.

A.     UTILISATION VUE JS SANS OUTIL DE DEVELOPPEMENT

 

Voici un exemple d'une page utilisant Vue.js

(index.html)

<html>

    <head>

        <title>Ma page Vue.js</title>

    </head>

    <body>

        <div id="app">

            {{ title }}

        </div>

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

        <script src="./app.js"></script>

    </body>

</html>

 

(app.js)

// fonction qui permet d'initialiser Vue.js

const vm = Vue.createApp({     // le const vm = est facultatif mais plus pratique

    data() {

        return {

            title: "Hello Word Vue"

        }

    }

}).mount('#app')

// mount spécifie que l'application Vue s'affichera dans la div avec id="app"

Ou

const vm = {

    data() {

        return {

            title: "Hello Word Vue"

        }

    }

}

Vue.createApp(vm).mount('#app')

 


 

A-1.   Variables Reactive

La fonction data() sert à créer des variables réactives qui seront utilisées dans votre application Vue. Chaque fois qu'une variable réactive est modifiée, si elle est affichée ou utilisée dans votre page, Vue la mettra à jour immédiatement.

Pour afficher une variable réactive ou une expression dans votre page vous devez utiliser les doubles crochets Vue remplacera le contenu de l'expression par sa valeur

// variable

{{ title }}

 

// expression

{{ title.toUpperCase() }}

 

A-2.   Les directives Vue.js

Les directives Vue.js sont des attributs html qui peuvent être insérés dans votre page afin de modifier le rendu de votre application Vue.

Voici la liste des directives disponibles:

v-bind

Permet d'assigner une expression à un attribut. Vue va remplacer l'expression par sa valeur

(ex: image_url : "http://www.exemple.com/car.jpg" dans app.js)

<img v-bind:src="image_url" />

 

// ou syntaxe raccourci

<img :src="image_url" />

v-once

Avec la directive v-once Vue va interpoler l'expression seulement une fois. L'expression sera donc ignorée pour tous les autres rafraichissements.

<div v-once>

   {{ title }}

</div>

v-html

Permet d'afficher une expression avec des tags HTML.

ex: title: "

Hello World

"

<div v-html="title">

</div>

 

Illustration TD1_base et TD2_base.

v-model

Permet de lier la valeur d'un champ de saisie avec une variable. Si vous modifiez l'un ou l'autre Vue mettra a jour automatiquement l'autre. Du coup, la variable et le champ de saisie auront toujours la même valeur.

<input v-model="name" type="text" />

<div>

    Nom : {{ name }}

</div>

 

Illustration TD3_v-model.

 

 

v-if, v-else-if et v-else

Rend un élément visible ou non visible selon la valeur vrai ou faux de l'expression. Lorsque non visible l'élément n'est pas rendu dans le html

<div v-if="montant > 100">

    Livraison gratuite!

<div>

<div v-else-if="montant > 50">

    Livraison 9.95$

</div>

<div v-else>

    Livraison 19.95$

</div>

v-show

Rend un élément visible ou non visible selon la valeur vrai ou faux de l'expression. Par contre, l'élément reste toujours présent dans le rendu. Lorsque non visible l'élément est rendu avec l'attribut CSS: display: none;

<div v-show="isError">

  {{ errorMessage }}

</div>

v-for

Permet d'afficher une liste d'éléments

<ul>

    <li v-for="item in items" :key="item.id">

        {{ item.name }}

    </li>

</ul>

À noter le mot clé "key" est nécessaire pour permettre à Vue d'identifier uniquement l'élément

Illustration TD4_directive_v-for.


 

Ref

Permet à l'application Vue d'identifier un élément html et d'effectuer des actions sur cet élément.

Identification avec la directif ref

<input type="text" ref="name">

Manipulation à partir de votre code Vue en utilisant le mot clé spécial: $refs

methods: {

  handleClick() {

    console.log(this.$refs.name)

    this.$refs.name.classList.add('active')

    this.$refs.name.focus()

  }

}


 

v-bind sur l'attribut "class" et les "style"

Il est possible de faire un v-bind sur l'attribut class et style

<div class="text-2xl" :class="isAdmin ? 'text-red-500' : 'text-gray-500'">

   Hello World

</div>

À noter que l'attribut class est utilisé deux fois (une fois pour le css, une fois par Vue).

Vue va regrouper ces deux attributs lors du rendu.

Il est également possible d'utiliser un objet pour envoyer du contenu dans notre attribut "class"

<div :class="{ 'text-red-500': isAdmin, 'text-gray-500': !isAdmin }">

   Hello World

</div>

À noter la syntaxe de l'object { attribut : expression } si l'expression retourne vrai alors l'attribut sera ajouter à la class

Une syntaxe similaire s'applique à l'attribut style

<div :style="{'margin-top': '10px', 'padding': '5px'}">

   Hello World

</div>

Enfin les attributs class et style peuvent être définis par une variable de type objet créé ailleurs dans votre application

titleClass: {

    'text-red-400': this.isAdmin,

    'text-gray-500': !this.isAdmin

}

<div :class="titleClass">

   Hello World

</div>

 

L'élément

Cet élément permet d'utiliser des directives de Vue sans créer un élément html.

<template v-show="quantity === 0">

    La quantité doit être supérieure à zéro

</template>


 

A-3.   Les Évènements

Vue permet de gérer les évènements javascript comme click, input, change, etc. Pour ce faire vous devez utiliser la directive v-on: suivi du nom de l'évènement.

v-on:click

Permet d'exécuter du code sur le click d'un élément

<button v-on:click="name = 'Mike'">Afficher message</button>

 

// ou syntaxe raccourci

<button @click="name = 'Mike'">Afficher message</button>

v-on:keydown

Permet d'exécuter du code sur l'appui d'une touche (ex. enter)

<button v-on:keydown.enter="name = 'Mike'">Afficher message</button>

 

// ou syntaxe raccourci

<button @keydown.enter="name = 'Mike'">Afficher message</button>

Autres valeurs possibles pour v-on : keydown, keyup, keypress

Autres valeurs possibles pour .enter : tab, esc, up, down, left, right, delete

v-on:submit

Permet d'exécuter du code lors de la soumission d'un formulaire

<form v-on:submit.prevent="name = 'Mike'">

    <input v-model="name" type="text" />

    <button type="submit">Sauvegarde</button>

</form>

À noter, la présence de ".prevent" après la directive v-on:submit. Cette instruction va prévenir la soumission du formulaire au serveur.


 

A-4.   Les méthodes

Vue js permet de créer des méthodes afin d'y placer un bloc de code réutilisable dans votre application. Voici la syntaxe pour créer une méthode:

Vue.createApp({

    data() {

        return {

            name: "Mike Taylor",

        }

    },

    methods: {

        resetName() {

            this.name = ''

        }

    }

}).mount('#app')

À noter le mot clé 'this' placé en avant de la variable name. Ce mot clé est obligatoire pour permettre de référencer une variable à l'intérieur de notre instance de Vue.

Pour appeler une méthode vous pouvez le faire simplement en utilisant son nom.

<input v-model="name" type="text" />

<button @click="resetName" type="text">Effacer</button>

Une méthode peut également contenir des paramètres

methods: {

    resetName(newName) {

        this.name = newName

    }

 }

<input v-model="name" type="text" />

<button @click="resetName('John')" type="text">Effacer</button>

Une méthode peut également envoyer l'objet event

methods: {

    resetName(newName, e) {

        this.name = newName

        console.log(e.target.textContent)

    }

 }

<input v-model="name" type="text" />

<button @click="resetName('John', $event)" type="text">Effacer</button>

À noter le paramètre spécial $event va envoyer l'objet event à notre méthode

Illustration TD5_methode&evenement.


 

Les méthodes "computed"

Contrairement aux autres méthodes qui vont se ré-exécutées à chaque rendu de votre application, les méthodes "computed" vont être ré-exécutées seulement si les variables qu'elles contiennent sont modifiées.

computed: {

    recalculerTotal(items, taxes) {

        return  this.calculerTotal(items, taxes)

    }

}

Les méthodes "computed" peuvent ensuite être appelées dans notre page.

<button @click="recalculerTotal">Re-Calculer</button>

À noter qu'aucun paramètre ni parenthèse n'est utilisé

Les méthodes "watch"

Ces méthodes vont "regarder" une variable et dès qu'elle change exécutera le code de la méthode.

watch: {

    title(newTitle, oldTitle) {

        console.log(`Le titre ${oldTitle} à changé pour ${newTitle}`)

    }

}

Les méthodes "Lifecycle Hook"

Chaque instance de vue traverse une série d’étapes d’initialisation au moment de sa création - par exemple, elle doit mettre en place l’observation des données, compiler le template, monter l’instance sur le DOM et mettre à jour le DOM quand les données changent.

En cours de route, elle va aussi invoquer des hooks de cycle de vie, qui nous donnent l’opportunité d’exécuter une logique personnalisée à chaque étape.

Par exemple, le hook "created" est appelé une fois l’instance créée

created() {

    console.log('Mon instance est created')

  }

Il existe plusieurs autres méthodes hook. En voici quelques-unes:

A-5.   Les "Components" (composants)

Vue.js est un framework qui permet et encourage l'organisation de votre application en plusieurs "components"et sous "components"

Chaque élément distinct de votre page devra avoir son propre component. Par exemple la barre de navigation pourrait être contenu dans un component NavBar réutilisé sur plusieurs pages

Voici la syntaxe pour créer des "components" et utiliser Vue seulement dans une petite partie de votre page.

const app = Vue.createApp({

    data() {

        return {

            messsage: 'Un message'

        }

    },

    methods: {

        deleteUser(userID) {

            console.log(`User ${userID} deleted`)

        }

    }

})

 

app.component('nav-bar', {

    template: `

        <div>

            {{ title }}

            ...navigation bar code...

        </div>

    `,

    props: {

        title: {

            type: String,

            required: true,

            default: 'Mon application'

        }

    },

    methods: {

        sendDelete() {

            const userId = 10

            this.$emit('delete', userId)

        }

    }

})

 

app.mount('#app')

Les components crées peuvent ensuite être utilisés comme des tags HTML dans votre page

<div>

    <nav-bar title="Mon application" v-on:delete="deleteUser($event)" />

</div>

L'élément "template" contient le HTML qui sera rendu à l'endroit où vous avez placé votre tag component dans votre page html

L'objet "props" définit quelle data est attendue lors du rendu du component

props: {

    title: {

        type: String,

        required: true,

        default: 'Mon application'

    }

},

Props peut également être utilisé avec une syntaxe raccourci

props: ['title'],

Vous pouvez par la suite assigner une valeur à ces props lors de l'utilisation du component

<div>

    <nav-bar title="Mon application" />

</div>

Enfin, le mot-clé $emit permet d'émettre un événement. Cet évènement pourra ensuite être capté par votre application avec un v-on:nom-event

methods: {

    sendDelete() {

        const userId = 10

        this.$emit('delete', userId)

    }

}

<div>

    <nav-bar title="Mon app" v-on:delete="deleteUser" />

</div>

 

 

Illustration TD6_composant.


 

B.  CREER UNE APPLICATION VUE JS AVEC L'OUTIL DE DEVELOPPEMENT VUE CLI

L'outil pour créer un projet Vue.js est Vue CLI. Vous devrez l'installer

npm install -g @vue/cli                      ou avec yarn (c'est ce que nous utiliserons)

Vue create

Permet de créer un projet Vue.js avec plein d'éléments déjà préconfigurés pour vous.

vue create my-app-name

npm run serve

Une fois l'application créée vous pouvez vous positionner dans le dossier et lancer le serveur de développement.

cd my-app-name

npm run serve

Vue add

Il est possible d'ajouter des plugin/librairie à votre projet Vue en utilisant le raccourci vue add. Voici 3 exemples:

vue add vue-router

vue add vuex

vue add tailwind

Point de départ

Vue CLI va créer plusieurs dossiers et fichiers. Le point de départ est public/index.html et "src/main.js"

import { createApp } from "vue";

import App from "./App.vue";

 

createApp(App).mount("#app");

Le component qui sert de point d'entrée est donc App.vue

Avec une application Vue, aucun code HTML ne sera écrit dans le fichier index.html. Votre code HTML sera écrit dans la section de chacun de vos components


 

Vite

Il est également possible de créer un projet avec Vite. C'est un outil plus récent et plus efficace

npm init @vitejs/app my-app-name --template vue

Cette commande va créer exactement un projet Vue.js avec les mêmes pré-configurations que le Vue-CLI

Avec un projet Vite, la commande pour lancer le serveur est

npm install

npm run dev

Les Single-File Component

Chaque component Vue est défini dans son propre fichier .vue avec la syntaxe suivante

<template>

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

    <HelloWorld msg="Hello Vue 3 + Vite" />

    {{ message }}

</template>

 

<script>

    import HelloWorld from './components/HelloWorld.vue'

 

    export default {

        components: {

            HelloWorld

        },

        data() {

             return {

                message: 'Hello World'

            }

        },   

    }

</script>

 

<style scope >

    #app {

      font-family: Avenir, Helvetica, Arial, sans-serif;

      text-align: center;

      color: #2c3e50;

    }

</style>

À noter qu'avec l'utilisation des single-file-component, le code HTML du component est saisi dans la section template. Il n'est pas saisi dans la div #app de votre index.html

Comme démontré dans le dernier exemple, Il est possible d'utiliser un autre component à l'intérieur de votre component actuel.

<template>

    <HelloWorld msg="Hello Vue 3 + Vite" />

</template>

Pour cela il faut utiliser import:

import HelloWorld from './components/HelloWorld.vue'

Emplacement des fichiers components

Les Single-File-Component sont sauvegardés dans un dossier src/components ou src/pages selon si le component agit à titre de page (ex. About.vue) ou à titre de component ré-utilisable (ex. NavBar.vue)

Les Slots

Les slots permettent d'ajouter du contenu à un component

<custom-button>

    Je peux ajouter du contenu...

  Titre: {{ title }}

</custom-button>

À noter que le rendu de 'title' se fera dans le component parent. Le même principe s'appliquera pour le css. Donc le contenu de la slot doit être défini/accessible dans le component parent

À l'interne le custom-button ressemble à quelque chose comme ceci:

<template>

    <slot></slot>

</template>

La balise slot va être remplacée par le contenu de 'custom-button'

Il est possible de définir une valeur par défaut pour la slot

<template>

    <slot>Si rien n'est spécifier je vais m'afficher</slot>

</template>

À noter que la valeur par défaut est défini dans le component enfant, donc devra utiliser les variables ou le css défini dans le component enfant.


 

Les slots multiples

Permet d'ajouter du contenu associé seulement à un slot en particulier

<custom-button>

    Je peux ajouter du contenu...

  <template #title>

    {{ title }}

  </template>

</custom-button>

'#title' indentifie la template au slot title. La syntaxe v-slot:title peut également être utilisé.

À l'interne le custom-button ressemble à quelque chose comme ceci :

<template>

    <slot></slot>

  <slot name="title"></slot>

</template>

À noter que le slot principal est toujours disponible

(les balises ici sont optionnelles) mais il est possible d'ajouter un second slot avec un nom

Slot Props

Les slots peuvent avoir des props

<template>

  <slot name="title" satus="info"></slot>

</template>

Les Props peuvent ensuite être utilisés

<custom-button>

    Je peux ajouter du contenu...

  <template #title="titleProps">

    {{ title }}

    {{ titleProps.status }}

  </template>

</custom-button>

Il est possible de définir des Props pour les slot principal en utilisant '#defaut'

<template>

    <slot type="ajout"></slot>

  <slot name="title" status="info"></slot>

</template>

<custom-button>

  <template #default="defaultProps">

       Je peux ajouter du contenu...

     {{ defaultProps.type }}

  </template>

  <template #title="titleProps">

    {{ title }}

    {{ titleProps.status }}

  </template>

</custom-button>

À noter que si il n'y a pas de named slot. Il est possible d'utiliser les Props du default avec cette syntaxe

<custom-button #default="defaultProps">

       Je peux ajouter du contenu...

     {{ defaultProps.type }}

</custom-button>