Vue 3 Reactivity Transform en 2026 : $ref, $computed et Questions d'Entretien

Guide complet sur le Reactivity Transform de Vue 3, incluant $ref, $computed, les macros de réactivité et les questions d'entretien technique fréquentes.

Vue 3 Reactivity Transform avec $ref et $computed

Le Reactivity Transform de Vue 3 représente une évolution majeure dans la façon dont les développeurs travaillent avec la réactivité. Cette fonctionnalité expérimentale, introduite pour simplifier la syntaxe du Composition API, a connu plusieurs itérations avant d'atteindre sa forme actuelle en 2026. Comprendre son fonctionnement, ses avantages et ses limitations constitue un atout essentiel pour tout développeur Vue cherchant à maîtriser les concepts avancés du framework.

État du Reactivity Transform en 2026

Le Reactivity Transform a été officiellement stabilisé dans Vue 3.5. Les macros $ref, $computed et $shallowRef sont désormais disponibles via un plugin Vite dédié, distinct du core de Vue.

Comprendre le Problème que Résout le Reactivity Transform

Le Composition API standard de Vue 3 exige l'utilisation de .value pour accéder et modifier les valeurs réactives créées avec ref(). Cette syntaxe, bien que explicite, introduit une charge cognitive supplémentaire et peut générer des bugs subtils lorsque le développeur oublie d'utiliser .value.

typescript
import { ref, computed } from 'vue'

// Syntaxe standard du Composition API
const count = ref(0)
const doubled = computed(() => count.value * 2)

function increment() {
  count.value++ // .value requis
}

console.log(doubled.value) // .value requis aussi

Le Reactivity Transform élimine ce besoin en transformant automatiquement le code au moment de la compilation. Les variables déclarées avec les macros de réactivité se comportent comme des variables JavaScript normales tout en conservant leur nature réactive.

Les Macros $ref et $computed

Les macros $ref et $computed constituent le cœur du Reactivity Transform. Elles permettent de déclarer des valeurs réactives sans avoir à manipuler .value manuellement.

vue
<script setup>
// Avec Reactivity Transform
let count = $ref(0)
const doubled = $computed(() => count * 2)

function increment() {
  count++ // Pas de .value nécessaire
}

console.log(doubled) // Accès direct
</script>

<template>
  <button @click="increment">{{ count }} (doubled: {{ doubled }})</button>
</template>

Le compilateur Vue transforme ce code en syntaxe standard avec ref() et .value avant l'exécution. Cette transformation est transparente pour le développeur et ne modifie pas le comportement du code.

Comment Fonctionne la Transformation

Le compilateur analyse le code et applique les transformations suivantes :

  1. $ref(value) devient ref(value)
  2. Les accès à la variable deviennent variable.value
  3. Les assignations deviennent variable.value = newValue
typescript
// Code source avec Reactivity Transform
let message = $ref('Bonjour')
message = 'Au revoir'
console.log(message)

// Code transformé par le compilateur
const message = ref('Bonjour')
message.value = 'Au revoir'
console.log(message.value)

Configuration du Reactivity Transform avec Vite

L'activation du Reactivity Transform nécessite une configuration spécifique dans le projet Vue. En 2026, cette fonctionnalité est fournie via le plugin @vue/reactivity-transform.

vite.config.tstypescript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { reactivityTransform } from '@vue/reactivity-transform'

export default defineConfig({
  plugins: [
    vue(),
    reactivityTransform()
  ]
})

Pour les projets utilisant TypeScript, une configuration supplémentaire assure la reconnaissance des types des macros.

tsconfig.jsonjson
{
  "compilerOptions": {
    "types": ["@vue/reactivity-transform"]
  }
}

$shallowRef et Autres Macros Avancées

Outre $ref et $computed, le Reactivity Transform inclut d'autres macros pour des cas d'usage spécifiques.

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

// $shallowRef pour les objets volumineux
let largeObject = $shallowRef({ data: [], metadata: {} })

// Seule la référence est réactive, pas les propriétés internes
largeObject = { data: [1, 2, 3], metadata: { updated: true } }

// $toRef pour convertir une prop en ref
const props = defineProps<{ initialValue: number }>()
let value = $(props.initialValue) // Équivalent à toRef(props, 'initialValue')

watchEffect(() => {
  console.log('Value changed:', value)
})
</script>

La Macro $() pour la Déstructuration Réactive

La macro $() permet de déstructurer des objets réactifs tout en préservant la réactivité de chaque propriété extraite.

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

const state = reactive({
  firstName: 'Jean',
  lastName: 'Dupont',
  age: 30
})

// Déstructuration avec préservation de la réactivité
const { firstName, lastName } = $(state)

// firstName et lastName restent réactifs
function updateName() {
  firstName = 'Pierre' // Modifie state.firstName
}
</script>

Intégration avec les Composables

Le Reactivity Transform s'intègre naturellement avec les composables, simplifiant leur utilisation et leur création.

composables/useCounter.tstypescript
export function useCounter(initial = 0) {
  let count = $ref(initial)
  const doubled = $computed(() => count * 2)
  const isEven = $computed(() => count % 2 === 0)

  function increment() {
    count++
  }

  function decrement() {
    count--
  }

  function reset() {
    count = initial
  }

  // $$() convertit les refs en objets ref standard pour le retour
  return $$({ count, doubled, isEven, increment, decrement, reset })
}

L'utilisation du composable devient plus intuitive.

vue
<script setup>
import { useCounter } from '@/composables/useCounter'

// Déstructuration avec $() pour conserver la réactivité
const { count, doubled, increment, reset } = $(useCounter(10))
</script>

<template>
  <div>
    <p>Count: {{ count }} (Doubled: {{ doubled }})</p>
    <button @click="increment">+</button>
    <button @click="reset">Reset</button>
  </div>
</template>

Gestion des Props avec le Reactivity Transform

La conversion des props en refs réactives modifiables localement représente un cas d'usage fréquent du Reactivity Transform.

vue
<script setup>
const props = defineProps<{
  modelValue: string
  disabled?: boolean
}>()

const emit = defineEmits<{
  'update:modelValue': [value: string]
}>()

// Création d'une ref locale liée à la prop
let localValue = $ref(props.modelValue)

// Synchronisation bidirectionnelle
watch(
  () => props.modelValue,
  (newVal) => { localValue = newVal }
)

watch(
  () => localValue,
  (newVal) => { emit('update:modelValue', newVal) }
)
</script>

<template>
  <input v-model="localValue" :disabled="disabled" />
</template>

Questions d'Entretien Technique sur le Reactivity Transform

Les entretiens techniques sur Vue 3 incluent fréquemment des questions sur le Reactivity Transform. Les questions suivantes représentent les sujets les plus couramment abordés.

Question 1 : Quelle est la différence entre $ref et ref ?

Réponse attendue : $ref est une macro de compilation qui génère du code utilisant ref() avec accès automatique à .value. La différence est purement syntaxique au niveau du code source. À l'exécution, les deux produisent le même résultat. $ref améliore l'ergonomie du développeur en éliminant la nécessité d'écrire .value manuellement.

Question 2 : Pourquoi utiliser $$() lors du retour de valeurs depuis un composable ?

Réponse attendue : La macro $$() convertit les variables transformées par Reactivity Transform en objets ref standard. Sans cette conversion, les valeurs retournées seraient des primitives perdant leur réactivité. $$() assure que le consommateur du composable reçoit des refs réactives qu'il peut utiliser avec $() pour la déstructuration.

Question 3 : Le Reactivity Transform fonctionne-t-il avec les Options API ?

Réponse attendue : Non. Le Reactivity Transform est conçu exclusivement pour le Composition API avec <script setup>. Il s'appuie sur l'analyse statique du code à la compilation, ce qui n'est pas compatible avec la structure dynamique de l'Options API.

Question 4 : Comment déboguer du code utilisant le Reactivity Transform ?

Réponse attendue : Le code source visible dans les outils de développement est le code transformé, pas le code original. Pour déboguer efficacement, il est recommandé d'utiliser les source maps et de comprendre la transformation appliquée. Vue DevTools affiche correctement les valeurs réactives indépendamment de la syntaxe utilisée.

typescript
// Pour voir la ref sous-jacente pendant le débogage
let count = $ref(0)
console.log($$(count)) // Affiche l'objet ref complet

Question 5 : Quels sont les pièges courants du Reactivity Transform ?

Réponse attendue : Les pièges principaux incluent :

  • Oublier $$() lors du retour de valeurs depuis des fonctions
  • Mélanger la syntaxe standard et la syntaxe transformée dans le même fichier
  • Assumer que toutes les opérations JavaScript fonctionnent identiquement (certaines assignations complexes peuvent nécessiter une attention particulière)
  • Ne pas configurer correctement TypeScript pour reconnaître les types des macros

Comparaison avec la Syntaxe Standard

Une comparaison directe illustre les différences entre les deux approches.

vue
<!-- Sans Reactivity Transform -->
<script setup>
import { ref, computed, watch } from 'vue'

const items = ref<string[]>([])
const filter = ref('')
const filteredItems = computed(() =>
  items.value.filter(item => item.includes(filter.value))
)

function addItem(item: string) {
  items.value.push(item)
}

watch(filter, (newFilter) => {
  console.log('Filter changed:', newFilter)
})
</script>
vue
<!-- Avec Reactivity Transform -->
<script setup>
import { watch } from 'vue'

let items = $ref<string[]>([])
let filter = $ref('')
const filteredItems = $computed(() =>
  items.filter(item => item.includes(filter))
)

function addItem(item: string) {
  items.push(item)
}

watch($$(filter), (newFilter) => {
  console.log('Filter changed:', newFilter)
})
</script>

Prêt à réussir tes entretiens Vue.js / Nuxt.js ?

Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.

Bonnes Pratiques et Recommandations

L'adoption du Reactivity Transform dans un projet existant nécessite une approche méthodique pour maintenir la cohérence du code.

Cohérence au sein du projet : Choisir une approche (standard ou transformée) et l'appliquer uniformément. Mélanger les deux syntaxes complique la lecture et la maintenance du code.

Documentation explicite : Documenter l'utilisation du Reactivity Transform dans le README du projet et les guides de contribution. Les nouveaux développeurs doivent comprendre la syntaxe utilisée.

Tests unitaires : Les tests fonctionnent identiquement quelle que soit la syntaxe utilisée, car le code est transformé avant l'exécution. Aucune modification des tests existants n'est nécessaire lors de la migration.

Migration progressive : Pour les projets existants, migrer fichier par fichier plutôt que de tout convertir simultanément. Cette approche réduit les risques d'introduction de bugs.

Le Reactivity Transform représente une amélioration significative de l'ergonomie du développement Vue 3. Sa maîtrise démontre une compréhension approfondie du système de réactivité de Vue et constitue un avantage lors des entretiens techniques pour des postes de développeur Vue senior.

Défi du jour

Tu saurais repérer le bug en Vue.js / Nuxt.js ?

Un vrai bout de code, un bug caché, une tentative par jour. Sans compte pour essayer.

Anthony Fillion-Maillet

Écrit par

Anthony Fillion-Maillet

Fondateur de SharpSkill

Développeur fullstack depuis plus de 10 ans. Il dirige SharpSkill et répond de tout ce qui y est publié.

Mis à jour le 9 septembre 2026

Tags

#vue 3
#reactivity transform
#composition api
#entretien technique

Partager

Articles similaires