4 min de lecture
Vue 3 au quotidien, ce que j’utilise vraiment
Vue a beaucoup d’outils. Après plusieurs projets en production, voici la petite partie que j’utilise tous les jours, et pourquoi j’ai laissé le reste de côté.
Mélanie Da Silva, développeuse front-end
- Vue
- TypeScript
- Front-end
Quand on apprend Vue, on a l’impression qu’il faut tout connaître : les deux API, les mixins, les directives personnalisées, les render functions, Pinia, les plugins. En pratique, sur les projets que je livre, j’utilise une partie assez réduite de tout ça. Elle tient dans cet article.
<script setup> et rien d’autre
Tous mes composants sont écrits en <script setup lang="ts">. Pas d’Options API, même dans un vieux projet qu’on reprend : je migre le composant que je touche, et je laisse les autres jusqu’à ce que je les touche.
La raison n’est pas la mode. C’est que le code se lit de haut en bas, que TypeScript comprend tout sans annotation, et qu’un composable s’appelle comme une fonction ordinaire. Un composant de cinquante lignes en <script setup> se comprend en une lecture.
Des props typées, pas des objets de configuration
<script setup lang="ts">
import type { Project } from '~/data/projects'
const props = defineProps<{
project: Project
compact?: boolean
}>()
const emit = defineEmits<{
open: [slug: string]
}>()
</script>
Deux habitudes ici. D’abord, le type vient du modèle de données, pas d’une redéfinition locale : si Project change, le composant le sait. Ensuite, defineEmits avec des types nommés. L’éditeur complète l’événement et son argument, et une faute de frappe dans un @open devient une erreur à la compilation.
defineModel pour tout ce qui se saisit
Avant, un champ contrôlé demandait une prop modelValue, un événement update:modelValue et un computed pour relier les deux. Depuis defineModel, c’est une ligne :
<script setup lang="ts">
const phone = defineModel<string>({ default: '' })
</script>
<template>
<input v-model="phone" type="tel" inputmode="tel" autocomplete="tel">
</template>
Le composant parent fait <PhoneField v-model="form.phone" /> et tout circule. Je l’utilise pour chaque champ de formulaire, chaque interrupteur, chaque sélecteur.
Les composables, pour une seule raison
Un composable, chez moi, existe quand la même logique réactive apparaît dans deux composants. Pas avant. Les trois que j’emporte de projet en projet :
useMediaQuery('(min-width: 1024px)'), pour adapter un comportement, pas un style (le style, c’est le rôle du CSS).useTheme(), qui lit et écrit la préférence clair ou sombre.useScrub(el, offset), qui transforme la position de défilement d’un élément en une valeur entre 0 et 1, pour les animations liées au scroll.
Ils font chacun moins de trente lignes. Un composable de deux cents lignes est en général un composant qui s’ignore.
computed plutôt que watch
Chaque fois que je suis tentée d’écrire un watch pour recalculer une valeur, je vérifie si un computed ne suffit pas. Neuf fois sur dix, oui. Le computed dit ce qu’est la valeur ; le watch dit quand la recalculer, et c’est là que les bugs de synchronisation se cachent.
Je garde watch pour les effets de bord : appeler une API, écrire dans le stockage, lancer une animation.
Le state global, le plus tard possible
Pinia est très bien. Mais la plupart des données d’un écran appartiennent à cet écran. Je commence toujours par un ref local, je passe des props vers le bas et des événements vers le haut, et je ne crée un store que quand deux pages éloignées ont vraiment besoin de la même donnée vivante : la session de l’utilisateur, un panier, un brouillon qui doit survivre à la navigation.
Un projet avec un seul store de vingt lignes est souvent en meilleure santé qu’un projet avec douze stores.
Ce que je n’utilise presque jamais
- Les mixins. Un composable fait la même chose en lisible.
provideetinjecten dehors des bibliothèques de composants. Dans une application, c’est du state global qui ne dit pas son nom.- Les render functions. Utiles dans une bibliothèque, inutiles dans une page.
v-htmlavec du contenu qui ne vient pas de moi.
Le mot de la fin
Vue permet beaucoup de choses, et c’est tant mieux. Mais un projet qu’on peut reprendre six mois plus tard est un projet qui utilise peu de choses, toujours de la même façon. Ce que je décris ici tient sur une page, et c’est volontaire : c’est ce qu’un nouveau venu doit lire pour contribuer dès le premier jour.