Je vais simplement expliquer pourquoi il existe 2 façons de créer un état réactif :
D'autres réponses montrent déjà les différences entre les deux
reactive
: Crée un état réactif. Renvoie un proxy réactif de l'objet :
import { reactive } from 'vue'
const reactiveObj = reactive({ count: 0 })
reactiveObj.count++
Avec l'API Options, nous avions l'habitude de conserver l'état réactif dans data()
. Avec l'API Composition, nous pouvons obtenir le même résultat avec l'API reactive
. Jusque-là, tout va bien, mais...
Pourquoi avons-nous besoin de ref
???
Tout simplement parce que reactive
a des limitations telles que :
-
Perte de réactivité :
const state = reactive({ count: 0 })
// la fonction reçoit un nombre simple et
// ne pourra pas suivre les changements de state.count
callSomeFunction(state.count)
const state = reactive({ count: 0 })
let { count } = state
// n'affecte pas l'état d'origine
count++
let state = reactive({ count: 0 })
// cela ne fonctionnera pas !
state = reactive({ count: 1 })
-
Il ne peut pas contenir des types primitifs tels que string, number ou boolean.
Ainsi, ref
, a été fourni par Vue pour pallier les limitations de reactive
.
ref()
prend l'argument et le renvoie encapsulé dans un objet ref avec une propriété .value :
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
Les Refs peuvent :
-
contenir n'importe quel type de valeur
-
remplacer réactivement l'objet entier :
const objectRef = ref({ count: 0 })
// cela fonctionne de manière réactive
objectRef.value = { count: 1 }
-
être passés dans des fonctions ou déstructurés à partir d'objets simples sans perdre la réactivité
const obj = {
foo: ref(1),
bar: ref(2)
}
// la fonction reçoit un ref
// elle doit accéder à la valeur via .value mais elle
// conservera la connexion réactive
callSomeFunction(obj.foo)
// toujours réactif
const { foo, bar } = obj
Devrais-je toujours utiliser ref
?
Opinion personnelle à suivre
La plupart des développeurs qui ont essayé les deux, suggèrent d'utiliser ref
d'après les articles que j'ai lus.
Mais personnellement, je pense que ref
a les mêmes limitations que reactive
s'il n'est pas utilisé correctement et vous pouvez facilement tomber dans des problèmes de "Perte de réactivité". ref
a également quelques comportements comme :
- le déballage dans les templates mais cela se produit uniquement pour les propriétés de premier niveau
- le déballage à l'intérieur de
reactive
- aucun déballage n'est effectué lorsque le ref est accédé à partir d'un tableau ou d'un type de collection natif comme Map
- Synchronisation des refs
Aussi, devoir traiter avec .value
à chaque fois est un peu déroutant, Vue le sait et il y a un RFC - Réactivité Transform à l'heure où j'écris ceci qui vise à fournir une solution.
J'espère que vous avez maintenant une meilleure compréhension de reactive
et ref
mais je pense qu'il est utile de mentionner qu'il y a plus d'API pour l'état réactif dont vous devriez être conscient : readonly, shallowRef, shallowReactive, shallowReadonly, unref, et bien d'autres encore.