• Contenu
  • Bas de page
logo ouidoulogo ouidoulogo ouidoulogo ouidou
  • Qui sommes-nous ?
  • Offres
    • 💻 Applications métier
    • 🤝 Collaboration des équipes
    • 🛡️ Sécurisation et optimisation du système d’information
    • 🔗 Transformation numérique
  • Expertises
    • 🖥️ Développement logiciel
    • ♾️ DevSecOps
    • ⚙️ Intégration de logiciels et négoce de licences
      • Atlassian : Jira, Confluence, Bitbucket…
      • Plateforme monday.com
      • GitLab
      • SonarQube
    • 📚​ Logiciel de CRM et de gestion
    • 🎨 UX/UI design
    • 🌐 Accessibilité Numérique
    • 🗂️​ Démarches simplifiées
    • 📝 Formations Atlassian
  • Références
  • Carrières
    • 🧐 Pourquoi rejoindre Ouidou ?
    • ✍🏻 Nous rejoindre
    • 👨‍💻 Rencontrer nos collaborateurs
    • 🚀 Grandir chez Ouidou
  • RSE
  • Ressources
    • 🗞️ Actualités
    • 🔍 Articles techniques
    • 📖 Livres blancs
    • 🎙️ Interviews Clients
Nous contacter
✕
Images, Lazy loading ou Chargement paresseux
Images, Lazy loading ou Chargement paresseux
19 avril 2018
Rendering avancé avec Vue.js
Rendering avancé avec Vue.js
3 mai 2018
Ressources > Articles techniques > Introduction à Vue.js, partie 3 — du POC à l’état de l’art

Introduction à Vue.js, partie 3 — du POC à l’état de l’art

Article écrit par Tom Panier

Vous l’attendiez, vous en rêviez, voici la troisième et dernière partie de cette introduction au framework Vue.js ! Cette fois encore, nous allons travailler sur la merveilleuse application que nous avons ébauchée ensemble et qui nous permet, je vous le rappelle, de gérer facilement une collection d’URLs d’images ou de vidéos, et de copier ces dernières dans le presse-papiers en un clic pour pouvoir harceler votre entourage !

Aujourd’hui, nous allons transformer notre proof of concept en une application construite et industrialisée dans les règles de l’art. Sans perdre une minute de plus, entrons si vous le voulez bien dans le vif du sujet !

Une app, une vraie

Si notre unique fichier JavaScript a rempli son office jusqu’ici, il est pour nous grand temps de passer à l’étape suivante : du code correctement découplé, avec notamment un fichier .vue par composant. L’ennui, c’est que la compilation de ces fichiers en code compréhensible par le navigateur est potentiellement chronophage à mettre en place à la main, à grands coups de configuration Webpack et Babel. Fort heureusement, l’écosystème Vue.js comprend un outil en ligne de commande permettant de construire un projet avec tout ce qu’il faut en un tournemain. Commençons donc par l’installer :

$ npm install -g vue-cli 

Puis exécutons-le directement dans le dossier de notre application, et laissons-nous guider :

$ vue init webpack .  ? Generate project in current directory? Yes ? Project name memebox ? Project description Meme collection displayer with easy copypasting ? Author Tom Panier <tpanier@synbioz.com> ? Vue build standalone ? Install vue-router? No ? Use ESLint to lint your code? No ? Set up unit tests No ? Setup e2e tests with Nightwatch? No ? Should we run `npm install` for you after the project has been created? (recommended) npm     vue-cli · Generated "memebox".     To get started:       npm run dev     Documentation can be found at https://vuejs-templates.github.io/webpack 

Que s’est-il passé ? Nous constatons que beaucoup de fichiers ont été créés, et que notre index.html, notamment, a été remplacé. Pour l’heure, lançons, comme il nous est indiqué, npm run dev (ou npm start, ce qui revient au même) :

 DONE  Compiled successfully in 3147ms   I  Your application is running here: http://localhost:8080 

Rendons-nous donc sur http://localhost:8080 :

Capture%20d%E2%80%99e%CC%81cran%202018-03-23%20a%CC%80%2014.47.00_thumb_650.png

Effectivement, notre application a « disparu » au profit d’une page de garde, certes élégante, mais peu utile en pratique ! Pas de panique, nous allons voir ensemble comment la remettre sur pied.

Composant monofichier

Lors de la partie 2 de ce tutoriel, nous avions mis en place un composant Meme destiné à isoler la logique d’un élément de notre grille d’images et de vidéos. Dans cette nouvelle configuration, ce dernier va donc fort logiquement être placé dans un fichier autonome, à savoir src/components/Meme.vue :

<template>   <div     class="meme-container"     :class="{ 'meme-container-clicked': clicked }"     @click="copy"     @mouseleave="hover"   >     <iframe       v-if="isEmbed"       class="meme"       :src="previewUrl"       frameborder="0"       allowfullscreen     ></iframe>     <div       v-else       class="meme"       :style="{ backgroundImage: 'url(' + previewUrl + ')' }"     ></div>   </div> </template>  <script> export default {   props: { url: String },   data: () => ({ clicked: false }),   computed: {     isEmbed() {       return /youtu/.test(this.url);     },     previewUrl() {       return getEmbedUrl(this.url) || this.url;     }   },   methods: {     copy() {       copyToClipboard(this.url);       this.clicked = true;     },     hover() {       this.clicked = false;     }   } }; </script> 

Un composant monofichier (en anglais, SFC) est ainsi constitué de deux balises élémentaires :

  • <template>, contenant comme de raison le squelette du composant (équivalent du champ éponyme dans notre ancien fichier app.js)
  • <script>, qui doit exposer un module ES6 contenant le reste de la configuration du composant (là aussi, c’est strictement identique à ce que nous avions précédemment écrit)

Il est également possible de déclarer une balise <style> pour injecter du CSS (ou des langages préprocessés dérivés de ce dernier, d’ailleurs).

Il ne reste qu’un détail à régler : notre code fait référence à nos deux fonctions getEmbedUrl et copyToClipboard, qui ne sont pour le moment pas disponibles dans ce contexte ! Nous pourrions les insérer au début de la balise <script>, mais n’avions-nous pas décidé de faire les choses proprement ? Créons donc deux fichiers dans le dossier src, respectivement getEmbedUrl.js :

export default function getEmbedUrl(url) {   let ytId = url.match(/youtu.be/([a-zA-Z0-9_-]+)/);   ytId = ytId || url.match(/youtube.com.*(?|&)v=([a-zA-Z0-9_-]+)/);    return ytId     ? "https://www.youtube.com/embed/" + ytId.pop()     : null; } 

Et copyToClipboard.js :

export default function copyToClipboard(text) {   const textArea = document.createElement("textarea");   textArea.value = text;   document.body.appendChild(textArea);   textArea.select();   document.execCommand("copy");   document.body.removeChild(textArea); } 

Il ne nous reste plus qu’à importer ces deux nouveaux modules là où nous en avons besoin, à savoir dans notre composant :

import getEmbedUrl from "../getEmbedUrl"; import copyToClipboard from "../copyToClipboard";  export default {   // ... }; 

Point d’entrée et composant racine

Si nous ôtons d’app.js le code que nous venons de déplacer, et excluons le tableau où nous stockons nos URLs, il ne reste pas grand-chose :

new Vue({   el: "#app",   data: { urls },   components: { Meme } }); 

Il s’agit, en somme, du point d’entrée de notre application ; nous pouvons retrouver du code très similaire dans le fichier src/main.js généré par vue-cli :

import Vue from "vue"; import App from "./App";  Vue.config.productionTip = false;  new Vue({   el: "#app",   render: h => h(App) }); 

Ouvrons maintenant le fichier src/App.vue, référencé ci-dessus (et ôtons-en au passage la balise <style>, inutile dans notre cas) :

<template>   <div id="app">     <img src="./assets/logo.png" />     <HelloWorld />   </div> </template>  <script> import HelloWorld from "./components/HelloWorld";  export default {   components: { HelloWorld } }; </script> 

Ce composant (car c’en est bien un), référencé directement par le point d’entrée, constitue la racine des vues de notre application : son rendu est effectué en premier, et de lui découle le rendu de tous les autres composants. Modifions-le un brin, en reprenant le code qui se trouvait précédemment dans notre index.html :

<template>   <div id="app" class="memebox">     <meme       v-for="url in urls"       :key="url"       :url="url"     />   </div> </template>  <script> import Meme from "./components/Meme";  export default {   components: { Meme } }; </script> 

Le composant déclarant lui-même ses dépendances (en l’occurrence, le composant Meme), nous n’avons pas besoin de modifier le code du point d’entrée !

Il reste toutefois, là encore, un problème de référence : la fameuse variable urls censée contenir notre précieuse collection…

Configuration et coup de polish

Il est temps de dire au revoir pour de bon à notre fichier app.js : tout son contenu a été déplacé, hormis le tableau contenant les URLs des images et vidéos à afficher sur l’application. Pour le remplacer, créons à la racine du projet un fichier urls.json :

[   "http://sarakha63-domotique.fr/wp-content/uploads/2017/03/Shut-up-and-take-my-money.jpg",   "https://www.youtube.com/watch?v=XMdoGqcnBoo" ] 

Ensuite, chargeons-le directement comme un module au sein du composant racine, à savoir src/App.vue, et référençons son contenu comme un membre de data, là encore tel que nous le faisions dans index.html précédemment :

import urls from "../urls"; import Meme from "./components/Meme";  export default {   data: () => ({ urls }),   components: { Meme } }; 

Notez que data doit être une fonction qui retourne un objet, afin d’éviter que plusieurs instances d’un même composant partagent leurs données.

Vous pouvez dès lors supprimer app.js, ainsi que le dossier src/assets et le fichier src/components/HelloWorld.vue. Si vous avez laissé tourner la commande npm run dev tout à l’heure, retournez sur votre navigateur, et…

Capture%20d%E2%80%99e%CC%81cran%202018-03-23%20a%CC%80%2016.13.28_thumb_650.png

L’application générée par vue-cli dispose en effet du hot reloading : en développement, toute modification dans le code est automatiquement répercutée dans le navigateur, et ce en conservant l’état courant !

Comme vous le constatez, il ne manque guère que le CSS à notre application pour fonctionner de nouveau comme avant ; plusieurs choix s’offrent à nous, notamment la balise <style> des composants que j’ai mentionnée plus haut, mais nous allons opter ici pour la simplicité et référencer directement app.css dans index.html.

Déplacez donc le fichier dans le dossier static, prévu à cet effet :

$ mv app.css static/ 

Et ajoutez cette ligne à l’intérieur de la balise <head> :

<link rel="stylesheet" href="/static/app.css" /> 

Bingo !

Capture%20d%E2%80%99e%CC%81cran%202018-03-23%20a%CC%80%2017.30.51_thumb_650.png

Bonus 1 : versioning de la configuration

Ce serait dommage de versionner urls.json : votre collection ne sera pas celle d’un·e autre utilisateur·rice. Un pattern simple à appliquer dans un tel cas est le suivant :

  • versionner un fichier d’exemple, nommé urls.json.dist
  • ajouter urls.json au .gitignore, pour éviter que lui-même soit versionné
  • indiquer dans la documentation et/ou automatiser via un script la copie du premier vers le second

Bonus 2 : grid finesse

Nous allons améliorer un brin le rendu de notre page, afin d’éviter qu’un élément se retrouve seul en dernière ligne dans certains cas. Ajoutez le code suivant à app.css :

.meme-container:nth-last-child(2):nth-child(10n) { // 10 éléments par ligne   min-width: 50%; } 

Bonus 3 : support direct des embed YouTube

Je vous propose une ultime retouche : le support des URLs de la forme https://www.youtube.com/embed/, y compris avec des paramètres en query string. Cela aura un avantage incommensurable : le fait de pouvoir préciser un début et une fin à la vidéo YouTube partagée !

Voici un exemple pas piqué des hannetons.

Afin de pouvoir nager définitivement dans le bonheur, voici la modification à apporter à src/getEmbedUrl.js :

// Avant : let ytId = url.match(/youtu.be/([a-zA-Z0-9_-]+)/);  // Après : let ytId = url.match(/(youtu.be|youtube.com/embed)/([a-zA-Z0-9_-]+)/); 

Ayé

Nous en avons fini ! Notre application est désormais fonctionnelle et construite selon les standards de l’industrie — en tout cas, c’est un bon début : nous pourrions envisager de tester unitairement nos méthodes et composants, ou encore d’automatiser les vérifications syntaxiques et stylistiques grâce à ESLint (dans les deux cas, je le rappelle, vue-cli nous mâche le travail de mise en place des outils nécessaires). Nous explorerons certainement ces possibilités lors de prochains articles.

Si cela vous intéresse, vous pouvez retrouver sur Github l’application terminée.

Quant à moi, je vous dis à très bientôt pour de nouvelles aventures avec Vue.js !

À lire aussi

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique

Lire la suite

intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 

Lire la suite

Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 

Lire la suite

image miniature les nouveautés Atlassian
26 février 2025

Les nouveautés Atlassian en 2025

Lire la suite

Articles associés

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique


Lire la suite
intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 


Lire la suite
Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 


Lire la suite

À propos

  • Qui sommes-nous ?
  • Références
  • RSE
  • Ressources

Offres

  • Applications métier
  • Collaboration des équipes
  • Sécurisation et optimisation du système d’information
  • Transformation numérique

Expertises

  • Développement logiciel
  • DevSecOps
  • Intégration de logiciels et négoce de licences
  • Logiciel de CRM et de gestion
  • UX/UI design
  • Accessibilité Numérique
  • Démarches simplifiées
  • Formations Atlassian

Carrières

  • Pourquoi rejoindre Ouidou ?
  • Nous rejoindre
  • Rencontrer nos collaborateurs
  • Grandir chez Ouidou

SIEGE SOCIAL
70-74 boulevard Garibaldi, 75015 Paris

Ouidou Nord
165 Avenue de Bretagne, 59000 Lille

Ouidou Rhône-Alpes
4 place Amédée Bonnet, 69002 Lyon

Ouidou Grand-Ouest
2 rue Crucy, 44000 Nantes

Ouidou Grand-Est
7 cour des Cigarières, 67000 Strasbourg

  • Linkedin Ouidou
  • GitHub Ouidou
  • Youtube Ouidou
© 2024 Ouidou | Tous droits réservés | Plan du site | Mentions légales | Déclaration d'accessibilité
    Nous contacter