• 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
✕
Mettre en place le captcha de Google sur un formulaire
Mettre en place le captcha de Google sur un formulaire
18 avril 2017
Implémentation d’une blockchain
Implémentation d’une blockchain
18 janvier 2018
Ressources > Articles techniques > Introduction à Vue.js, partie 2 — vidéos et composants

Introduction à Vue.js, partie 2 — vidéos et composants

Ecrit par Tom Panier

Nous avons vu comment utiliser le framework pour mettre en place une application minimaliste permettant de stocker une collection d’URLs d’images et de copier ces dernières dans le presse-papiers facilement. Aujourd’hui, nous allons ajouter une nouvelle fonctionnalité à notre appli, et en profiter pour étudier de nouveaux concepts qui nous permettront de mieux organiser notre code. C’est parti !

La fonctionnalité : support des vidéos

Spammer ses collègues avec des GIFs, c’est bien ; le faire avec des vidéos YouTube, c’est encore mieux ! Nous allons donc faire en sorte de supporter les URLs de ces dernières, afin d’afficher un aperçu dans notre grille.

En premier lieu, il nous faut être en mesure d’exploiter une URL Youtube, afin d’en extraire l’identifiant de la vidéo et de pouvoir construire l’URL embed correspondante. Comme précédemment avec la gestion du presse-papiers, l’écriture de cette fonction n’est pas le but de cet article, je vous la fournis donc :

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; } 

Nous allons ensuite définir une nouvelle méthode sur notre application Vue.js (et, au passage, renommer images en urls, terme plus générique et représentatif) :

new Vue({   el: "#app",   data: {     urls,     clicked: false   },   methods: {     copy(url) {       copyToClipboard(url);       this.clicked = true;     },     hover() {       this.clicked = false;     },     getEmbedUrl(url) {       return getEmbedUrl(url);     }   } }); 

Il ne nous reste plus qu’à modifier notre fichier HTML en conséquence, en faisant appel à de nouvelles directives du framework, à savoir v-if et v-else :

<div id="app" class="memebox">   <div     v-for="url in urls"     :key="url"     class="meme-container"     :class="{ 'meme-container-clicked': clicked }"     @click="copy(url)"     @mouseleave="hover"   >     <iframe       v-if="getEmbedUrl(url)"       class="meme"       :src="getEmbedUrl(url)"       frameborder="0"       allowfullscreen     ></iframe>     <div       v-else       class="meme"       :style="{ backgroundImage: 'url(' + url + ')' }"     ></div>   </div> </div> 

Nous en profitons pour rectifier un oubli du premier article : lorsqu’on utilise v-for, il faut toujours l’accompagner d’un attribut key qui aura une valeur unique et constante pour chacun des éléments de la boucle. Cette dernière fonctionne sans, mais demande à Vue.js de faire davantage de calculs (et il vous enguirlandera dans la console — en toute amitié, mais à raison — si vous ne vous y pliez pas).

Afin de mutualiser les écouteurs d’évènements (et d’éviter d’être embêtés avec le rendu de nos iframes), nous ajoutons également un div.meme-container autour de chacun de nos éléments. Quelques ajustements sont également nécessaires côté CSS, afin de déporter une partie des styles de .meme vers .meme-container :

.meme-container {   flex: 1 0 10%;   position: relative;   min-width: 175px;   min-height: 175px; }  .meme-container:before {   content: "Copy URL";   display: none;   position: absolute;   z-index: 1;   top: 0;   right: 0;   bottom: 0;   left: 0;   background-color: rgba(0, 0, 0, 0.75);   line-height: 175px;   text-align: center;   color: white;   cursor: pointer; }  .meme-container:hover:before {   display: block; }  .meme-container-clicked:before {   content: "Copied!"; }  .meme {   width: 100%;   height: 100%;   background-position: center;   background-size: cover; } 

Pour tester vos modifications, ajoutez quelques URLs Youtube à votre collection :

const urls = [   "https://www.youtube.com/watch?v=XMdoGqcnBoo",   "https://www.youtube.com/watch?v=JwQY9GoLMvY",   "https://youtu.be/XE6YaLtctcI",   // ... ]; 

Notion de composant

Suite à l’implémentation de notre fonctionnalité, je ne sais pas pour vous, mais de mon côté, je commence à me dire qu’il y a beaucoup de code « global » :

  • l’intégralité du markup (collection et éléments)
  • la gestion du clic et du survol d’un élément
  • le parsing de l’URL d’un élément dans le but d’effectuer son rendu

On commence à voir apparaître un ensemble de code uniquement dédié à la gestion d’un élément au sein de notre collection. Un tel pattern, dans une interface réalisée à l’aide d’un framework tel que Vue.js, ne peut signifier qu’une chose : il est temps d’en dégager un composant !

Pour l’heure, nous conserverons nos uniques fichiers, la taille du code n’ayant pas augmenté de manière critique ; cela implique quelques contraintes, mais permettra de conserver des exemples très simples.

Commençons donc à définir notre composant :

const Meme = Vue.extend({   props: { url: String },   data: () => ({ clicked: false }) }); 

Avec Vue.js, un composant a grosso modo la même API que l’instance du framework lui-même : nous indiquons donc que le composant Meme va gérer tout seul son « état » (cliqué ou non) via ses propres data. Nous définissons également l’URL en tant que prop : il s’agit d’une donnée qui viendra de l’extérieur et devra être passée en « paramètre » lors de l’instanciation du composant — en d’autres termes, une propriété de ce dernier.

Une fois ces bases posées, nous pouvons très facilement porter les différentes méthodes actuellement attachées à l’application vers notre composant :

const Meme = Vue.extend({   props: { url: String },   data: () => ({ clicked: false }),   methods: {     copy() {       copyToClipboard(this.url);       this.clicked = true;     },     hover() {       this.clicked = false;     },     getEmbedUrl() {       return getEmbedUrl(this.url);     }   } }); 

L’avantage immédiatement visible est que ces méthodes n’ont plus besoin de prendre un paramètre puisque, contextualisées dans notre composant, elles peuvent directement référencer this.url. Mais nous pouvons faire encore mieux concernant getEmbedUrl, à savoir nous en débarrasser au profit d’une computed :

const Meme = Vue.extend({   props: { url: String },   data: () => ({ clicked: false }),   computed: {     previewUrl() {       return getEmbedUrl(this.url) || this.url;     }   },   methods: {     // ...   } }); 

Une computed, ou propriété calculée, sert à définir une représentation particulière de nos data, et a l’immense avantage d’être mise en cache par Vue.js, qui ne la réévaluera que si les data dont elle dépend venaient à changer — dans le cas contraire, la valeur calculée précédemment sera réutilisée telle quelle. Nous en profitons également, en la nommant previewUrl et en lui faisant retourner la data brute par défaut, pour lui donner une désignation plus générique (« ceci est l’URL à utiliser pour l’aperçu » et non plus « ceci est l’URL à utiliser si c’est une iframe, et null sinon »).

Au passage, définissons une seconde computed qui déterminera si oui ou non, l’URL du Meme courant correspond à un embed — l’implémentation sera, dans un premier temps, basique, mais pourra évoluer si nous souhaitons supporter d’autres plate-formes à l’avenir, par exemple :

const Meme = Vue.extend({   // ...   computed: {     isEmbed() {       return /youtu/.test(this.url);     },     previewUrl() {       return getEmbedUrl(this.url) || this.url;     }   },   // ... }); 

Poursuivons en décrivant le markup de notre composant ; le fait d’avoir conservé un seul fichier nous oblige à le faire sous forme de chaîne de caractères. Afin de pouvoir utiliser des retours chariot et autres joyeusetés, nous allons utiliser une template string :

const Meme = Vue.extend({   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>`,   // ... }); 

Il nous faut également fournir à notre application une référence vers notre composant, afin de pouvoir l’utiliser côté HTML :

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

…ce que nous faisons pour terminer :

<div id="app" class="memebox">   <meme     v-for="url in urls"     :key="url"     :url="url"   /> </div> 

Notez que les composants sont nommés en PascalCase dans le code JavaScript, mais respectent le standard des web components en utilisant la kebab-case dans le HTML.

C’est fini pour aujourd’hui

Notre petite application commence à prendre tournure ! Nous avons ajouté une killer feature, et créé notre premier vrai composant Vue.js ; la prochaine fois, nous verrons comment se rapprocher encore de l’état de l’art en termes de structure de projet. À très bientôt !

À 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