4e étageV VuePièce 3/7Débutant

La réactivité

Déclarer un état avec ref et reactive, calculer des valeurs dérivées avec computed et lier un champ de formulaire avec v-model.

Ce que tu vas apprendre

  • Déclarer un état réactif avec ref() et reactive().
  • Calculer une valeur à partir d'autres avec computed().
  • Lier un champ de formulaire à une variable avec v-model.

L'état réactif avec ref

Une variable JavaScript normale ne prévient pas Vue quand elle change. Pour que l'affichage suive, tu la déclares avec ref().

<script setup>
import { ref } from 'vue'

const portions = ref(4)

function ajouter() {
  portions.value++
}
</script>

<template>
  <button @click="ajouter">{{ portions }} portions</button>
</template>

ref() enveloppe la valeur dans un objet qui a une propriété .value. Dans le script, tu lis et modifies portions.value. Dans le template, Vue déballe automatiquement le ref : tu écris {{ portions }}, sans .value.

La documentation présente ref() comme l'API principale pour déclarer un état.

L'état d'un objet avec reactive

reactive() rend réactif un objet entier, sans passer par .value.

<script setup>
import { reactive } from 'vue'

const recette = reactive({ nom: 'Crêpes', minutes: 20 })

function allonger() {
  recette.minutes += 5
}
</script>

<template>
  <p>{{ recette.nom }} : {{ recette.minutes }} min</p>
  <button @click="allonger">+ 5 min</button>
</template>

Mais reactive() a des limites :

  1. Il ne fonctionne que sur les objets, tableaux, Map et Set, pas sur un nombre ou un texte.
  2. Tu ne peux pas remplacer l'objet entier (recette = {...}) : la réactivité serait perdue.
  3. Si tu extrais une propriété dans une variable (const { minutes } = recette), elle n'est plus réactive.

C'est pourquoi ref() est le choix par défaut, même pour un objet : const recette = ref({ ... }).

Dans le doute, utilise ref(). Tu écris .value dans le script, mais tu évites les pièges de reactive().

Les valeurs calculées : computed

Une propriété calculée est une valeur qui se déduit d'autres valeurs réactives. Tu la déclares avec computed().

<script setup>
import { ref, computed } from 'vue'

const prixParPortion = ref(2.5)
const portions = ref(4)

const total = computed(() => prixParPortion.value * portions.value)
</script>

<template>
  <p>Coût total : {{ total }} €</p>
</template>

Dès que prixParPortion ou portions change, total est recalculé. Dans le script, on lit un computed avec .value aussi (total.value).

Computed ou fonction ?

Une fonction appelée dans le template donnerait le même résultat. La différence tient au cache.

Propriété calculéeFonction
RecalculSeulement quand une dépendance change.À chaque nouvel affichage du composant.
ÉcritureEn lecture seule.Libre.

Une propriété calculée est en lecture seule : lui assigner une valeur déclenche un avertissement en console. Elle sert à calculer, jamais à modifier un état.

Une valeur non réactive, comme Date.now(), n'est pas suivie : un computed qui en dépend ne se mettra jamais à jour.

Lier un champ : v-model

v-model relie un champ de formulaire à une variable, dans les deux sens. Ce que tape l'utilisateur met à jour la variable, et inversement.

src/components/Recherche.vue
<script setup>
import { ref, computed } from 'vue'

const recherche = ref('')
const toutes = ['Tarte aux pommes', 'Crêpes', 'Soupe à l\'oignon']

const resultats = computed(() =>
  toutes.filter((nom) => nom.toLowerCase().includes(recherche.value.toLowerCase()))
)
</script>

<template>
  <input v-model.trim="recherche" placeholder="Chercher une recette" />
  <p v-for="nom in resultats" :key="nom">{{ nom }}</p>
</template>

Le modificateur .trim retire les espaces au début et à la fin de ce que tape l'utilisateur.

Remarque l'enchaînement : v-model alimente un ref, et un computed en tire la liste filtrée. C'est le schéma le plus courant dans une application Vue.

À retenir

  • ref() déclare un état réactif : .value dans le script, rien dans le template.
  • reactive() convient aux objets, mais perd la réactivité si tu le remplaces ou l'extrais.
  • computed() calcule une valeur dérivée, mise en cache et en lecture seule.
  • v-model relie un champ à une variable dans les deux sens ; .trim nettoie les espaces.
  • Un état se déclare une fois, et tout ce qui s'en déduit passe par computed().

Pour aller plus loin

Sources officielles

Ensuite

Projet
Lignes de code
Niveau
4e étage
Appartement
Vue
Pièce
3/7
Plan n°
vue/03.reactivite
Lignes de code · fiches rédigées à partir des documentations officielles, sources citées en bas de chaque page.