L'utilisation et le principe de Vue.set (analyse des séries de code source)

Série de code source d'analyse-Vue.set / vm.$setDétaillé

Description de la fonction et du concept

Document officiel: Vue-set

Ajoutez une propriété à l'objet responsive et assurez-vous que cette nouvelle propriété est également responsive et déclenche la mise à jour de la vue. Il doit être utilisé pour ajouter de nouvelles propriétés à l'objet réactif, car Vue ne peut pas détecter les nouvelles propriétés ordinaires (telles que this.myObject.newProperty = 'hi')

Limitations Il n'est
pas permis d'ajouter dynamiquement des attributs réactifs au niveau racine. tel que:

// 错误写法
this.$set(this, 'newkey', 1111)

// 正确写法
this.$set(this.obj, 'newkey', 111)

// 取值: this.obj.newkey => 111

résumé

  • Vue.setEt les vm.$setméthodes sont en fait les mêmes, mais le libellé n'est pas le même
  • L'effet est d'ajouter dynamiquement des attributs à la page, et les attributs ajoutés dynamiquement sont également des attributs réactifs

Pourquoi utiliser set pour ajouter des attributs réactifs

Look at vue Principe responsive: le principe de liaison de données vue bidirectionnelle
peut être vu en fait s'appuyer sur un responsive Object.defineProperty
et il Object.definePropertysuffit d'écouter l'un des attributs d'un objet, s'il y a plusieurs propriétés à écouter

Regardez une démo pour comprendre:

var data = {
    
    }

Object.defineProperty(data, 'data1', {
    
    
  get: function() {
    
    
    console.log('get data1')
    return this.value
  },
  set: function(newVal) {
    
    
    console.log('set data1')
    this.value = newVal
  }
})

data.data1 = 111 // 将会打印 set data1
console.log(data.data1) // 先打印 get data1  然后才是 111

data.data2 = 222 // 无打印,无报错
console.log(data.data2) // 直接打印222。表示没有进过 `Object.defineProperty`

Commencez à regarder le code source

Voici une démo pour le débogage

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
  var app = new Vue({
     
     
    el: '#app',
    data: {
     
     
      addData: {
     
     }
    }
  })
  debugger
  app.$set(app.addData, 'newkey', 1111)
</script>

Le premier à entrer les $setméthodes de l'époque, est arrivé en premier à la section valeur par défaut, cette fois pour renvoyer une valeur nulle, après le retour, ré-entrer $setest la partie que nous devons déboguer

En mode débogage, entrez la méthode définie

Ligne 2 1081 une méthode pour détecter le type de données du nœud cible, c'est $set-à- dire la détection du premier paramètre

  • 1085-1089 déterminent le type de la matrice. Après tout, comme le type spécial Object.defindPropetyne peut pas détecter la modification de la matrice, la modification de la matrice est mise à jour manuellement.
  • 1090-1093 est de déterminer si l'attribut existe déjà avant, et il n'est pas nécessaire de répéter la surveillance s'il existe
  • 1095-1100 est de déterminer que le nœud racine ne peut pas this.dataêtre ajouté directement aux données
  • Notez que 1094 variable de ligne obest observée (observateur) pour faire court. Il est également utilisé pour déterminer si la variable a été surveillée
  • Les valeurs qui ont été surveillées et qui n'ont pas besoin d'être surveillées à plusieurs reprises seront directement renvoyées aux valeurs correspondantes val. Il $setrenvoie également une valeur de retour de l'actuel
  • Si l'objet est nouveau, il est passé à la defineReactive$$1méthode de la ligne 1106

Ajouter une defineReactive$$1méthode d' écoute

  • 1021 initialize new Dep view l'analyse de dep look dep analyse est nécessaire. Cela implique la plupart des processus suivants. Le csdn ne prend pas en charge la navigation par hachage, vous devez donc le faire glisser manuellement vers le bas et jeter un œil ~
  • 1023-1026 Déterminer si l'objet est lisible et inscriptible
  • 1019-1033 obtenir l'objet getet la setméthode cibles .
  • 1035 Il y a une variable superficielle dans notre code précédent dans cette variable n'existe pas !shallowqui est vrai. Par conséquent, la mise en œuvre d'une observeméthode pour afficher l'analyse d'observation csdn ne prend pas en charge la navigation par hachage, vous devez faire glisser manuellement vers le bas sous leur propre pour voir ~
  • Après avoir lu l' observeanalyse ci-dessus , on sait observeque la propriété de son fils, le cyclisme ajoutent une écoute.
  • La ligne 1039 est liée à l'événement qui obtient la valeur de l'attribut.Lors de l'obtention de la valeur correspondante, je l'ai Dep.targetjuste vue comme un observateur global watch. Donc, s'il y a dep.targetappel à une cible pour la dependméthode actuelle , qui provient du Depfichier hérité. Cela équivaut à enregistrer un rappel pour regarder l'événement (qui est estimé watchet computedune préfiguration enterrée)
  • 1052 setméthode de la ligne de départ . Commencez également leur propre getterpour obtenir la valeur actuelle à l'intérieur
  • Ligne 1069, si nous copions un objet récemment, il doit rajouter une prise de données pour ces objets dans une boucle, si elle a déjà été maintenue, elle peut être ignorée, ce qui est le code ci-dessus
  • Les 1070 dernières lignes sont appelées après set dep.notify(). Il stocke l'heure à laquelle la mise à jour d'objet correspondante doit être déclenchée (mode observateur d'abonnement). Maintenant que la valeur est mise à jour, elle est déclenchée vers la fonction d'abonnement appropriée (la montre est également déclenchée à ce moment, et la vue est également mise à jour à ce moment) . Et nous devons obtenir la valeur définie avant le front, donc les watchméthodes à l'intérieur newValet oldValsont enregistrées à ce moment
  • Enfin, la valeur actuelle est renvoyée $setet l'exécution de la méthode est terminée



analyse dep

Le code dep n'est pas très long. dep équivaut à un centre d'abonnement

  • À la ligne 717, vous pouvez voir que chaque dép a un ID correspondant et qu'il augmente automatiquement
  • La ligne 718 peut être considérée comme un centre d'événements, et toute la surveillance est stockée ici
  • Vous pouvez voir qu'il existe plusieurs méthodes sur le prototype dep addSub removeSub depend notify. Ils sont tous utilisés pour faire fonctionner le moniteur correspondant, ajouter / supprimer, trouver la dépendance correspondante et notifier ces méthodes
  • La ligne 725 Dep.targeta des notes très détaillées, une visionneuse unique au monde

Le noyau est de se souvenir de quelques addSub removeSub depend notifyméthodes. Alors continuez à regarder le code juste maintenant

observer l'analyse

Notes particulièrement réfléchies

Tenter de créer une instance d'observateur pour une valeur,
essayer de créer une valeur pour l'instance d'observateur
renvoie le nouvel observateur s'il est observé avec succès,
s'il est observé avec succès, le nouvel observateur est renvoyé
ou l'observateur existant si la valeur en a déjà un.
Ou l'Observateur existant de (si la valeur en contient déjà un)

  • Il semble que value.__ob__s'il y en avait une, alors cette propriété aurait été un observateur, et c'est notre $setpremière étape dans un jugement quant à __ob__la

  • Distinguez ensuite le tableau, le tableau n'a pas d'observateurs

  • Principalement pour voir la ligne 1003, créez un nouvel observateur new Observenotez la majuscule, pas l'objet courant

  • new Observe Dans la figure 2 ci-dessous, je n'en parlerai pas séparément.

  • 926 lignes. Pour __ob__ajouter des propriétés, ne vous y trompez pas et __ob__définissez-le sur un type non énumérable. Pour plus de détails, vous pouvez voir le code qui va dans 926

  • 927-933 sont tous pour les opérations de baie

  • Ligne 935, la méthode de marche de l'objet courant. En collant directement le code, nous pouvons voir qu'il s'agit d'une boucle, parcourant notre objet une fois, et l'appelant pour chaque objet defineReactive$$1. Comme vous pouvez le voir, cette méthode ne sera appelée que si la valeur est un type d'objet.

  • Depuis qu'il est appelé defineReactive$$1. Puis une récursion se forme ici, la tête de la récursion est d'arrêter l'appel lorsque l'attribut n'est plus un objet defineReactive$$1.

  • Après avoir vu cela, l'étape suivante devrait revenir en arrière pour ajouter une méthode pour écouter la ligne 1035 de defineReactive $$

/**
 * Walk through all properties and convert them into
 * getter/setters. This method should only be called when
 * value type is Object.
 */
Observer.prototype.walk = function walk(obj) {
    
    
  var keys = Object.keys(obj)
  for (var i = 0; i < keys.length; i++) {
    
    
    defineReactive$$1(obj, keys[i])
  }
}

Pour résumer

  • vue responsive principe repose sur Object.defindPropetyles méthodes getet set, respectivement, dans ces deux méthodes pour déclencher l'événement correspondant

  • En raison de JS et des Object.defindPropetyrestrictions qui ne peuvent pas être ajoutées dynamiquement, il est nécessaire de surveiller la propriété, nous devons donc utiliser Vue.set()la méthode

  • Vue.set()L'intérieur de la méthode est un processus de traitement cyclique. Si le nouveau moniteur actuel est un objet, il continuera à s'appeler pour former une récursivité jusqu'à ce que le dernier sous-attribut soit un 数组/非对象类型paramètre, la récursion se termine, puis ajouter un moniteur pour vous-même, dans le moniteur Il déclenchera d'autres méthodes connexes (les événements souscrits dans Dep seront déclenchés). Former notre liaison de données bidirectionnelle commune

  • Étant donné que le Object.defindPropetychangement ne peut surveiller que l'objet, de sorte que la valeur d'un index particulier dans le changement de tableau n'est pas à l'écoute, il doit donc être utilisé Vue.setpour déclencher manuellement une mise à jour, cette fois Vue.setne faites que la valeur mise à jour et ne répétera pas la surveillance de la nouvelle augmentation

Article original d'abord: Analysez la série de code source-Vue.set / vm.$setExplication détaillée Ceci est la nouvelle adresse du blog, vous pouvez jeter un oeil si vous êtes intéressé

Je suppose que tu aimes

Origine blog.csdn.net/Jioho_chen/article/details/107005845
conseillé
Classement