Maison > Article > interface Web > vue3 solution de réponse de valeur originale et comment résoudre le problème de la perte de réponse
ref vise à résoudre le problème selon lequel le proxy ne peut pas directement proxy la valeur d'origine. Examinons d'abord l'utilisation de ref :
const name = ref('小黑子')
Comment ref est-il implémenté ? En fait, il s'agit de "envelopper" la valeur d'origine avec un objet. Jetons un coup d'œil à l'implémentation de ref :
function ref(val){ // 使用对象包裹原始值 const wrapper = { value:val } // 利用 reactive 将对象变成响应式数据 return reactive(wrapper) }
ref L'implémentation est aussi simple que cela.
ref fait principalement ces deux choses en réponse à la valeur d'origine :
1. Utilisez un objet pour envelopper la valeur d'origine.
2. Utilisez réactif pour transformer l'objet package en données réactives.
Nous utilisons ref pour créer un objet réactif, mais comment distinguer si un objet est un objet normal ou un objet ref ? Ainsi notre isref apparaît.
Regardons son utilisation :
const name = ref('cj') console.log(isRef(name)); // true
Alors quel est son principe de mise en œuvre ? L'implémentation principale se trouve toujours dans l'API ref. Jetons un coup d'œil au code d'implémentation spécifique :
function ref(val){ const wrapper = { value:val } Object.defineProperty(warpper,'__v_isRef',{ value:true }) return reactive(wrapper) }
Il s'avère qu'il ajoute un attribut non énumérable et non inscriptible à l'objet package dans ref, et la valeur est vraie. . De cette façon, nous pouvons vérifier l'attribut pour déterminer s'il s'agit d'une référence.
function isRef(val) { return val.__v_isRef ?? false }
Qu'est-ce que la perte de réponse ? La perte de réponse signifie que les données réactives ne reçoivent pas de réponse. Regardons le code ci-dessous :
const obj = reactive({foo:1,bar:2}) const {foo,bar} = obj obj.foo++ // foo不会改变,还是 1
L'obj ci-dessus a perdu sa réponse, il ne déclenchera donc pas de nouveau rendu. Pourquoi cela se produit-il ? En fait, du fait de l'utilisation de l'affectation de structure, l'opérateur d'expansion l'invalidera également.
const obj = reactive({foo:1,bar:2}) const newObj = {...obj} obj.foo++ // newObj.foo不会改变,还是 1
Cela équivaut à redéfinir de nouvelles données, qui ne sont plus les données de réponse d'origine et n'ont naturellement pas de capacités réactives.
toRef sert à résoudre le problème de la perte de réponse. Jetons un coup d'œil à son implémentation :
function toRef(obj,key) { const wrapper = { get value() { return obj[key] }, set value(val) { obj[key] = val } } Object.defineProperty(wrapper,'__v_isRef',{ value:true }) return wrapper }
Pass en deux paramètres, le premier est des données réactives, et le second est une clé d'obj.
La première partie consiste à définir et déclarer un objet. L'objet définit d'abord l'obtention de l'attribut value pour accéder à la valeur toRef. La valeur de l'attribut correspondant aux données réactives entrantes sera renvoyée, puis définit l'ensemble de. l'attribut value pour Lorsque la valeur toRef est définie, le nouvel ensemble de valeurs est utilisé pour mettre à jour la valeur de l'attribut correspondant aux données réactives. En d'autres termes, l'objet renvoyé par toRef est toujours les données réactives utilisées.
La deuxième partie est utilisée pour définir les données renvoyées comme étant des données de référence. Étant donné que les données renvoyées par toRef sont similaires aux données de référence, dans un souci d'unification, elles sont directement considérées comme des données de référence.
La troisième partie consiste à renvoyer l'objet attribut déclaré correspondant aux données réactives
De cette façon, toRef résout le problème de perte de réponse.
toRefs consiste à déconstruire l'intégralité de l'objet réactif et à le rendre réactif. Le code d'implémentation est le suivant :
function toRefs() { const ret = {} for (const key in obj) { ret[key] = toRef(obj,key) } return ret }
Utilisez une boucle for pour convertir les attributs un par un. Jetons maintenant un coup d'œil à l'utilisation :
const obj = reactive({foo:1,bar:2}) const {foo,bar} = toRefs(obj) obj.foo++ // foo.value变为2了
Lorsque l'attribut est une valeur non originale, il peut toujours répondre après la déconstruction
const obj = reactive({foo:{age:18},bar:2}) const {foo,bar} = obj obj.foo.age++ // foo.age变为2了 obj.bar++ // bar没有改变,还是1
Pourquoi cela ? La raison est en fait très simple, car la valeur non originale se voit attribuer une adresse de référence, ce qui signifie que la variable déstructurée pointe toujours vers l'attribut des données réactives d'origine. La valeur d'origine est une simple affectation et ne répondra pas.
reactive 响应数据重新赋值后不再响应,ref 响应数据赋值后依然响应 let obj1 = reactive({foo:1,bar:2}) let obj2 = ref({foo:1,bar:2}) // 假如 obj1 与 obj2 直接展示在页面上 obj1 = {boo:2,far:3} // 页面 obj1 还是 {foo:1,bar:2} obj2.value = {boo:2,far:3} // 页面 obj2 变为 {boo:2,far:3} 了
Quelle est la raison de cela ? La réponse de réaffectation réactive est perdue, c'est-à-dire qu'un nouvel objet est réaffecté, et il devient naturellement des données ordinaires et ne répond plus. Et ref peut toujours répondre car ref est défini en interne. Le code est le suivant :
function ref(val){ const wrapper = { value:val set value(val) { // isObject 这里代表判断是否是非原始值的一个方法 value = isObject(val) === 'Object' ? reactive(val) : val } } Object.defineProperty(warpper,'__v_isRef',{ value:true }) return reactive(wrapper) }
Nous comprenons. En fait, ref détermine si la nouvelle valeur définie dans set est une valeur non originale. Si c'est le cas, appelez reactive pour la transformer en données réactives.
Lorsque nous utilisons des données réactives ref, nous pensons toujours que .value est nécessaire pour obtenir la valeur, ce qui augmente la charge mentale de l'utilisateur.
Est-il possible d'accéder directement à la valeur au lieu d'utiliser .value ?
Lorsqu'il est utilisé de cette manière, vous n'avez pas à vous soucier de savoir si certaines données sont des données de référence ou si vous devez obtenir la valeur via l'attribut value.
C'est là que notre réf. entre en jeu. unref implémente la possibilité de supprimer automatiquement la référence. La suppression automatique de la référence signifie que si l'attribut lu est une référence, la valeur de l'attribut value correspondant à la référence sera directement renvoyée.
Jetons un coup d'œil à l'implémentation de unref :
function unref(target) { return new Proxy(target,{ get(target,key,receiver) { const value = Reflect.get(target,key,receiver) return value.__v_isRef ? value.value : value }, set(target,key,newValue,receiver) { const value = target[key] if (value.__v_isRef) { value.value = newValue return true } return Reflect.set(target,key,newValue,receiver) } }) }
Nous avons constaté qu'unref utilise en interne Proxy pour proxy l'objet cible, reçoit un objet en tant que paramètre et renvoie l'objet proxy de l'objet. Lorsque nous accédons aux données unref, le get catcher est déclenché, puis le catcher détermine en interne si l'objet entrant est un objet ref, et si c'est le cas, il renvoie directement la .value de ref. Sinon, l'objet proxy est renvoyé directement.
Lors de la définition de la valeur de l'objet proxy renvoyé par unref, le set capture est déclenché. Si l'objet proxy est ref, la nouvelle valeur qui doit être définie est affectée à .value. Sinon, le processus d'affectation est effectué directement. .
Après avoir utilisé ref pour créer des données réactives et les afficher dans le modèle, pourquoi ne pas utiliser .value ?
{{ name }}
其实原因很简单,在组件 setup 中声明的 ref 响应式数据会传递给 unref 函数进行处理。所以在模板中访问 ref 的值,无需通过 value 属性来访问。
我们使用的 reactive 其实也是有 自动脱 ref 功能的,看一下下方例子:
const count = ref(0) const obj = reactive({conut}) obj.count // 0
我们可以看见 obj.count 是一个 ref 响应式数据。在 count 外层包裹一层对象,再传递给 reactive 后,再访问 obj.count 时就不需要再通过 value 属性访问值了。
也正是因为 reactive 内部也同样实现了自动脱 ref 的能力。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!