Maison  >  Article  >  interface Web  >  Une brève discussion sur la réactivité de Vue (méthode de mutation de tableau)

Une brève discussion sur la réactivité de Vue (méthode de mutation de tableau)

不言
不言original
2018-05-07 14:46:061582parcourir

Cet article présente principalement une brève discussion sur la réactivité de Vue (méthode de mutation de tableau), qui a une certaine valeur de référence. Maintenant, je le partage avec tout le monde. Les amis dans le besoin peuvent s'y référer

Avant-propos

De nombreux étudiants qui débutent dans l'utilisation de Vue constateront que lorsque la valeur du tableau change, la valeur change, mais la vue est effectivement indifférente, c'est parce que. le tableau est trop froid.

Après avoir vérifié les documents officiels, j’ai découvert que ce n’est pas que la déesse a trop froid, mais que vous n’avez pas utilisé la bonne méthode.

Il semble que si vous voulez que la déesse bouge toute seule, la clé est d'utiliser la bonne méthode. Bien que la méthode ait été donnée dans le document officiel, je suis vraiment curieux si vous souhaitez débloquer plus de postures, il faut d'abord entrer dans le cœur de la déesse, j'ai donc eu l'idée d'explorer le principe réactif de. Vue. (Si vous êtes prêt à décoller mon cœur couche par couche. Vous constaterez que vous serez surpris... Je suis accro aux hurlements des fantômes et je n'arrive pas à m'en sortir QAQ).

Rappel au premier rang, le principe de réactivité de Vue utilise principalement Object.defineProperty d'ES5. Les étudiants non informés peuvent afficher les informations pertinentes.

Pourquoi la baie ne répond-elle pas ?

Si vous y réfléchissez bien, la réponse de Vue est basée sur Object.definePropery. Cette méthode modifie principalement la description des propriétés de l'objet. Les tableaux sont en fait des objets, et en définissant les propriétés du tableau, nous devrions pouvoir produire des effets réactifs. Testez d’abord votre idée, retroussez vos manches et lancez-vous.


const arr = [1,2,3];

let val = arr[0];

Object.defineProperty(arr,'0',{
  enumerable: true,
  configurable: true,
  get(){
    doSomething();
    return val;
  },
  set(a){
    val = a;
    doSomething();
  }
});

function doSomething() {

}

Entrez ensuite arr, arr[0] = 2, arr respectivement dans la console, vous pouvez voir les résultats comme indiqué ci-dessous.


Hé, tout est comme prévu.

Ensuite, après avoir vu ce code, certains étudiants peuvent se poser des questions, pourquoi this[0] n'est-il pas renvoyé directement dans la méthode get() ? Mais devrions-nous utiliser val pour renvoyer la valeur ? Réfléchissez bien, putain ! ! ! C'est presque une boucle infinie. Pensez-y, get() lui-même consiste à obtenir la valeur de l'attribut actuel. L'appel de this[0] dans get() n'est-il pas équivalent à appeler à nouveau la méthode get() ? C'est tellement effrayant, tellement effrayant, que ça fait mourir de peur les ouvriers.


Bien que la déesse dans votre imagination puisse avoir cette posture, la déesse devant vous n'est en effet pas dans cette posture. Comment une personne comme moi, dont les attributs sont clairement révélés, peut-elle deviner la déesse ? pensée? Pourquoi ne pas répondre aux données de cette manière ? Peut-être parce que les tableaux et les objets sont encore différents, la définition des propriétés des tableaux peut provoquer des problèmes et des bugs. Ou cela peut être dû au fait qu'une grande quantité de données peut être générée au cours du processus d'interaction, entraînant une dégradation globale des performances. Il est également possible que l'auteur utilise d'autres méthodes pour obtenir l'effet de réponse aux données après avoir pesé le pour et le contre. De toute façon, je n'arrive pas à comprendre.


Pourquoi l'appel de la méthode native du tableau peut-il répondre ?

Pourquoi les données peuvent-elles répondre en utilisant ces méthodes de tableau ? Jetons d'abord un coup d'œil au code source de la partie tableau.


Pour faire simple, la fonction de def est de redéfinir la valeur de l'attribut objet.


//array.js
import { def } from '../util/index'

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
//arrayMethods是对数组的原型对象的拷贝,
//在之后会将该对象里的特定方法进行变异后替换正常的数组原型对象
/**
 * Intercept mutating methods and emit events
 */
[
 'push',
 'pop',
 'shift',
 'unshift',
 'splice',
 'sort',
 'reverse'
]
.forEach(function (method) {
 // cache original method
 //将上面的方法保存到original中
 const original = arrayProto[method]
 def(arrayMethods, method, function mutator (...args) {
  const result = original.apply(this, args)
  const ob = this.__ob__
  let inserted
  switch (method) {
   case 'push':
   case 'unshift':
    inserted = args
    break
   case 'splice':
    inserted = args.slice(2)
    break
  }
  if (inserted) ob.observeArray(inserted)
  // notify change
  ob.dep.notify()
  return result
 })
})

Publiez la partie déf du code


/**
 * Define a property.
 */
export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
 Object.defineProperty(obj, key, {
  value: val,
  enumerable: !!enumerable,
  writable: true,
  configurable: true
 })
}

array.js mute certaines méthodes de tableaux Prenons la méthode push comme exemple. La première chose est d'utiliser original = arrayProto['push'] pour enregistrer la méthode push native.


Ensuite, il est temps de définir la méthode de mutation. Pour la fonction def, si vous n'entrez pas dans les détails, def(arrayMethods,method,function(){}), cette fonction peut être grossièrement. exprimé comme arrayMethods[method ] = function mutator(){};

En supposant que la méthode push est appelée plus tard, la méthode mutator est en fait appelée. Dans la méthode mutator, la première chose est d'appeler l'original. enregistre la méthode push d'origine. Recherchez la valeur réelle. Un tas de texte semble vraiment abstrait, alors écrivez une version discrète du code pour exprimer la signification du code source.


const push = Array.prototype.push;

Array.prototype.push = function mutator (...arg){
  const result = push.apply(this,arg);
  doSomething();
  return result
}

function doSomething(){
  console.log('do something');
}

const arr = [];
arr.push(1);
arr.push(2);
arr.push(3);

Voir le résultat dans la console :.


Ensuite, le code


const ob = this.__ob__
  let inserted
  switch (method) {
   case 'push':
   case 'unshift':
    inserted = args
    break
   case 'splice':
    inserted = args.slice(2)
    break
  }
  if (inserted) ob.observeArray(inserted)
  // notify change
  ob.dep.notify()

dans le code source est Le doSomething() correspondant est


Dans ce code, le commentaire de deux mots notifier le changement est clairement écrit. Si vous ne connaissez pas ces deux mots, recherchez simplement sur Baidu. Je l'ai fait pour vous, ces deux mots signifient publier des modifications ! Chaque fois que cette méthode est appelée, la valeur sera calculée, puis d'autres choses seront faites, comme publier des modifications et observer de nouveaux éléments. Les autres processus de réponse ne seront pas abordés dans cet article.


[
 'push',
 'pop',
 'shift',
 'unshift',
 'splice',
 'sort',
 'reverse'
]

Il existe tellement de méthodes à l'heure actuelle. Tant que vous utilisez la bonne méthode, vous pouvez changer la posture de la déesse !


Résumé

Quant au titre, je l'ai changé encore et encore. Au début, il s'appelait Une brève analyse des principes de réponse de Vue, mais plus tard, je l'ai modifié. J'ai vu que le titre était trop gros. Commençons par le plus simple, commençons par les tableaux, et cet article ne prendra pas trop de temps à lire. S'il y a une erreur dans cet article qui pourrait induire les autres en erreur, veuillez la signaler, je vous en serais très reconnaissant.

Recommandations associées :

Une brève discussion sur le principe de réactivité des données Vue


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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn