Série de code source d'analyse-Vue.set / vm.$set
Détaillé
Répertoire d'articles
Description de la fonction et du concept
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.set
Et lesvm.$set
mé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.defineProperty
suffit 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 $set
mé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 $set
est 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.defindPropety
ne 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
ob
est 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$set
renvoie également une valeur de retour de l'actuel - Si l'objet est nouveau, il est passé à la
defineReactive$$1
méthode de la ligne 1106
Ajouter une defineReactive$$1
mé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
get
et laset
méthode cibles . - 1035 Il y a une variable superficielle dans notre code précédent dans cette variable n'existe pas
!shallow
qui est vrai. Par conséquent, la mise en œuvre d'uneobserve
mé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'
observe
analyse ci-dessus , on saitobserve
que 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.target
juste vue comme un observateur globalwatch
. Donc, s'il y adep.target
appel à une cible pour ladepend
méthode actuelle , qui provient duDep
fichier hérité. Cela équivaut à enregistrer un rappel pour regarder l'événement (qui est estiméwatch
etcomputed
une préfiguration enterrée) - 1052
set
méthode de la ligne de départ . Commencez également leur propregetter
pour 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 leswatch
méthodes à l'intérieurnewVal
etoldVal
sont enregistrées à ce moment - Enfin, la valeur actuelle est renvoyée
$set
et 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.target
a des notes très détaillées, une visionneuse unique au monde
Le noyau est de se souvenir de quelques addSub
removeSub
depend
notify
mé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$set
premiè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 Observe
notez 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 objetdefineReactive$$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.defindPropety
les méthodesget
etset
, respectivement, dans ces deux méthodes pour déclencher l'événement correspondant -
En raison de JS et des
Object.defindPropety
restrictions qui ne peuvent pas être ajoutées dynamiquement, il est nécessaire de surveiller la propriété, nous devons donc utiliserVue.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.defindPropety
changement 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.set
pour déclencher manuellement une mise à jour, cette foisVue.set
ne 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.$set
Explication détaillée Ceci est la nouvelle adresse du blog, vous pouvez jeter un oeil si vous êtes intéressé