Maison > Article > interface Web > Quel est le principe de réactivité de Vue ?
J'ai lu récemment de nombreux articles sur les principes de Vue. Avec l'aide de ces articles, j'ai essayé à plusieurs reprises de comprendre moi-même le code source de Vue. Enfin, je pense qu'il est temps de publier le contenu moi-même. J'espère pouvoir familiariser tout le monde avec Vue sous un angle différent de celui des autres articles. La signification de
var Dep = function Dep() { this.id = uid++ this.subs = [] }
Dep est naturellement dépendance (c'est-à-dire dépendance, un nom dans le domaine informatique).
Tout comme l'écriture d'un programme node.js, les dépendances de l'entrepôt npm sont souvent utilisées. Dans Vue, les dépendances font spécifiquement référence aux données traitées de manière réactive. Comme nous le mentionnerons plus tard, l'une des fonctions clés du traitement réactif est DefineReactive, qui est mentionnée dans de nombreux articles sur les principes de Vue. Une fois que
Dep est lié à chaque donnée réactive, les données réactives deviendront une dépendance (nom). Lors de l'introduction de Watcher ci-dessous, il sera mentionné que les données réactives peuvent être surveillées, calculées ou utilisées dans des modèles depend (verbe).
subs
Dep Il y a un attribut subs sous l'objet, qui est un tableau. Il est facile de deviner qu'il s'agit de la liste des abonnés. Les abonnés peuvent surveiller des fonctions, des fonctions calculées ou visualiser des fonctions de mise à jour.
Watcher est l'abonné mentionné dans Dep (à ne pas confondre avec l'observateur Observer plus tard).
Parce que la fonction de Watcher est de répondre aux mises à jour de Dep en temps opportun, tout comme la poussée d'abonnement de certaines applications. Si vous (Watcher) vous abonnez à certaines informations (Dep), il vous sera rappelé de les lire lorsque les informations sont disponibles. mis à jour.
deps
Semblable à Dep ayant l'attribut subs, l'objet Watcher a également l'attribut deps. Cela constitue une relation plusieurs-à-plusieurs entre Watcher et Dep. La raison de l'enregistrement mutuel est que lorsqu'une partie est autorisée, les objets associés peuvent être mis à jour dans le temps.
Watcher Comment générer
Les modèles de surveillance, de calcul et de rendu mentionnés à plusieurs reprises ci-dessus génèrent Watcher, qui est concis et facile à comprendre dans le code source de Vue :
Selon la relation entre les concepts ci-dessus, comment les faire correspondre et comment obtenir une mise à jour réactive des données ?
Définissons d'abord notre objectif : naturellement, lorsque les données sont mises à jour, la vue sera automatiquement actualisée pour afficher les dernières données. C'est la relation entre Dep et Watcher mentionnée ci-dessus. Les données sont Dep, et Watcher déclenche la fonction de rendu de page (c'est l'observateur le plus important). Mais une nouvelle question se pose : comment Dep sait-il que des Watchers dépendent de lui ? Vue adopte une méthode très intéressante : Avant d'exécuter la fonction de rappel du Watcher, notez d'abord ce qu'est le Watcher actuel (via Dep.target) Les données réactives sont utilisées pour exécuter la fonction de rappel. La fonction getter des données réactives sera inévitablement appeléefunction defineReactive(obj, key, val, customSetter, shallow) { var dep = new Dep() depsArray.push({ dep, obj, key }) var property = Object.getOwnPropertyDescriptor(obj, key) if (property && property.configurable === false) { return } // cater for pre-defined getter/setters var getter = property && property.get var setter = property && property.set var childOb = !shallow && observe(val) Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter() { var value = getter ? getter.call(obj) : val if (Dep.target) { dep.depend() if (childOb) { childOb.dep.depend() if (Array.isArray(value)) { dependArray(value) } } } return value }, set: function reactiveSetter(newVal) { var value = getter ? getter.call(obj) : val // 后半部分诡异的条件是用于判断新旧值都是 NaN 的情况 if (newVal === value || (newVal !== newVal && value !== value)) { return } // customSetter 用于提醒你设置的值可能存在问题 if ('development' !== 'production' && customSetter) { customSetter() } if (setter) { setter.call(obj, newVal) } else { val = newVal } childOb = !shallow && observe(newVal) dep.notify() }, }) }
Dep.prototype.depend = function depend() { if (Dep.target) { Dep.target.addDep(this) } } Watcher.prototype.addDep = function addDep(dep) { var id = dep.id if (!this.newDepIds.has(id)) { this.newDepIds.add(id) this.newDeps.push(dep) if (!this.depIds.has(id)) { dep.addSub(this) } } } Dep.prototype.addSub = function addSub(sub) { this.subs.push(sub) }
通过这几个函数,可以领略到了 Dep 和 Watcher 错综复杂的关系……不过看起来迂回,简单来说,其实做的就是上面说的互相添加到多对多列表。
你可以在 Dep 的 subs 找到所有订阅同一个 Dep 的 Watcher,也可以在 Watcher 的 deps 找到所有该 Watcher 订阅的所有 Dep。
但是里面还有一个隐藏问题,就是 Dep.target 怎么来呢?先放一放,后会作出解答。先接着看看 setter 函数,其中的关键是 dep.notify()。
Dep.prototype.notify = function notify() { // stabilize the subscriber list first var subs = this.subs.slice() for (var i = 0, l = subs.length; i < l; i++) { subs[i].update() } }
不难理解,就是 Dep 提醒他的订阅者列表(subs)里的所有人更新,所谓订阅者都是 Watcher,subs[i].update() 调用的也就是 Watcher.prototype.update。
那么来看一下 Watcher 的 update 做了什么——
Watcher.prototype.update = function update() { if (this.lazy) { this.dirty = true } else if (this.sync) { this.run() } else { queueWatcher(this) } }
在这里我觉得有两个点比较值得展开,所以挖点坑
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!