Maison  >  Article  >  interface Web  >  Quel est le principe de réactivité de vue ? Analyse du principe de réactivité de vue

Quel est le principe de réactivité de vue ? Analyse du principe de réactivité de vue

不言
不言original
2018-09-10 15:33:512601parcourir

Cet article vous apporte quel est le principe de la réactivité de vue ? L'analyse du principe de réactivité de Vue a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer, j'espère qu'elle vous sera utile.

initState

new Vue() => , watch appelle la fonction d'initialisation correspondante

function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}

initProps et initData

Le travail principal est d'appeler définirProperty pour monter get pour les propriétés respectivement (lorsque ce hook est déclenché, les propriétés actuelles seront L'instance dep est poussée dans le Dep.target actuel, qui est le deps de l'observateur actuel, c'est-à-dire les dépendances qu'il auquel s'abonne Dep.target sera discuté ci-dessous, et l'instance dep poussera également l'observateur actuel, c'est-à-dire l'observateur dans son tableau subs, méthode set (informe tous les observateurs des sous-marins dépendants d'appeler leur méthode de mise à jour). .

initComputed

Sa fonction est de parcourir toutes les propriétés de l'objet calculé et de donner à la propriété un nouvel observateur calculé (une dépendance dep est définie dans la propriété calculée, Abonnez-vous à l'observateur qui doit utiliser la propriété calculée). Il montera également les méthodes get (méthode get) et set sur calculées en appelant DéfinirProperty (la méthode set déterminera si elle est transmise, et si elle n'est pas transmise, elle sera définie sur une fonction vide noop) La méthode get de l'attribut calculé est la valeur de retour de la fonction suivante Function


Faites attention à watcher.depend() Cette méthode permet à l'observateur qui utilise cet attribut de s'abonner à la dépendance. dans l'observateur, et l'observateur d'attribut calculé poussera l'observateur qui y est abonné dans ses sous-marins (lorsque la valeur de l'attribut calculé change, les observateurs qui y sont abonnés sont avertis)

watcher.evaluate(), cette méthode. consiste à appeler la méthode get de l'observateur (il convient de noter que la méthode get de l'observateur appellera pushTarget pour pousser l'instance Dep.target précédente sur la pile et définira Dep.target pour qu'il soit calculé observateur, la propriété réactive dont dépend la propriété calculée sera L'observateur est poussé dans ses sous-marins, donc lorsque la propriété réactive dépendante change, l'observateur calculé qui y est abonné sera averti, observateur calculé Informez ensuite l'observateur abonné à l'attribut calculé d'appeler la méthode de mise à jour) et appelez la fonction de gestionnaire liée à la clé d'attribut calculée dans la méthode get pour calculer la valeur.
function createComputedGetter (key) {
  return function computedGetter () {
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      watcher.depend()
      return watcher.evaluate()
    }
  }
}


initWatch

Cet observateur est un observateur utilisateur (personnalisé par le développeur dans le composant). La fonction de initWatch est de parcourir les propriétés de la montre et d'appeler le $watch défini pour chaque propriété surveillée par la montre


Lorsque un nouveau Watcher est appelé dans le code, il sera exécuté tout comme render watcher. Ensuite, utilisez la méthode get de l'observateur et appelez pushTarget pour attribuer l'observateur de l'utilisateur actuel à Dep.target. La valeur de l'instruction = this.getter.call(vm, vm) dans get() déclenchera l'obtention. méthode de l'attribut réactif surveillé par l'observateur personnalisé et modifiez l'utilisateur actuel. l'observateur pousse les sous-marins dont dépend cet attribut, donc lorsque l'utilisateur Une fois l'ensemble de propriétés surveillé par l'observateur déclenché, l'observateur abonné à la dépendance est averti de déclencher la mise à jour, c'est-à-dire que le gestionnaire correspondant à la clé liée à l'observateur est déclenché. Appelez ensuite popTarget pour afficher la pile et l'attribuer à Dep.target.

Vue.prototype.$watch = function (
    expOrFn: string | Function,
    cb: any,
    options?: Object
  ): Function {
    const vm: Component = this
    if (isPlainObject(cb)) {
      return createWatcher(vm, expOrFn, cb, options)
    }
    options = options || {}
    options.user = true // 代表该watcher是用户自定义watcher
    const watcher = new Watcher(vm, expOrFn, cb, options)
    if (options.immediate) {
      cb.call(vm, watcher.value)
    }
    return function unwatchFn () {
      watcher.teardown()
    }
  }
$mount

Le travail d'initialisation d'initState est grossièrement effectué ici, puis $mount sera exécuté pour commencer le travail de rendu

Le travail principal de $mount : créer un nouveau Watcher de rendu et utilisez updateCompent comme rappel Lors de sa transmission et de l'exécution du nouveau Watcher parmi les


trois observateurs, seul l'observateur calculé n'exécutera pas sa méthode get() au début. Le nouvel observateur de rendu dans $mount appellera la méthode get() et pushTarget pour attribuer l'observateur de rendu actuel à Dep.target. Vient ensuite le point culminant, l'appel à updateComponent, qui exécutera vm._update(vm._render(), hydrating), dans lequel la fonction de rendu déclenchera le get hook des attributs réactifs utilisés en HTML. Le hook get amènera le dépôt d'instance dépendant de la propriété responsive à convertir le rendu actuel L'observateur est poussé dans son tableau subs, donc lorsque les propriétés réactives dépendantes changent, il traversera les sous-marins pour avertir l'observateur qui y est abonné d'appeler update().

updateComponent = () => {
      vm._update(vm._render(), hydrating)
    }
new Watcher(vm, updateComponent, noop, {
    before () {
      if (vm._isMounted) {
        callHook(vm, 'beforeUpdate')
      }
    }
  }, true /* isRenderWatcher */)
Exemple

Peut-être que vous ne savez pas comment ajuster le watcher et le dep. Laissez-moi vous donner un exemple

Je vais commencer directement par le rendu et ne parler que de cela. le dépôt suivant est lié à l'observateur

$mount : nouveau un observateur de rendu (la méthode get de l'observateur attribuera l'observateur de rendu à Dep.target) lorsque vm._update(vm._render(), hydrating), render's À ce moment, les attributs réactifs utilisés en HTML seront obtenus. Dans l'exemple ci-dessus, a est utilisé en premier, et le get hook de a sera déclenché. Parmi eux, dep.depend() poussera l'observateur de rendu actuel dans les sous-marins de dep. l'attribut a dans le tableau.
<div id="app">
      <div>{{a}}</div>
      <div>{{b}}</div>
    </div>
new Vue({
  el: "#app",
  data() {
    return {
      a:1,
    }
  },
  computed:{
    b() {
      return a+1
    }
  },
})

Continuez l'exécution et accédez à b (b est la valeur de l'attribut calculé), ce qui déclenchera la méthode get de l'attribut calculé. La méthode get des propriétés calculées est la fonction ComputedGetter renvoyée après l'appel de la fonction createComputedGetter watcher.depend() est exécutée dans la fonction ComputedGetter. La méthode depend de Watcher est réservée exclusivement aux calculs Utilisé par l'observateur.

Comme mentionné ci-dessus, en plus de l'observateur calculé, les deux autres observateurs sont dans de nouveaux Après cela, leurs méthodes get seront exécutées, puis calculées Que fait l'observateur une fois le nouveau terminé ? Il créera un nouveau dépôt.

Retournez à la méthode watcher.depend() que nous venons de mentionner pour le watcher calculé. Sa fonction est d'exécuter this.dep.depend() (le dep défini par le watcher calculé est utilisé ici). this.dep.depend() amènera l'observateur de rendu actuel à s'abonner à la dépendance de la propriété calculée. La propriété calculée poussera également l'observateur de rendu dans ses propres sous-marins ([render watcher] lorsque la valeur de la propriété calculée est modifiée). , il avertira l'observateur dans les sous-marins d'appeler update(), afin que la page puisse être actualisée si la valeur de l'attribut calculée change.

Retournez au hook get qui a déclenché l'attribut calculé de b. Le hook get exécutera finalement watcher.evaluate(), et watcher.evaluate() exécutera la méthode get() de l'observateur calculé.

Le point clé arrive à ce moment-là. Dep.target (observateur de rendu) sera poussé dans la pile targetStack (après avoir été stocké afin de pouvoir être retiré plus tard pour une utilisation continue), puis l'observateur calculé. de cet attribut calculé sera attribué à Dep .target. Dans la méthode get, value = this.getter.call(vm, vm) exécutera le gestionnaire lié à l'attribut calculé.

Renvoyer un + 1 comme dans l'exemple ci-dessus. Si a est utilisé, le hook get de a sera déclenché, et le hook get appellera dep.depend() amènera l'observateur calculé à stocker dep dans son tableau deps, et le dep de a stockera le dep actuel. . Dep.target (observateur calculé) est stocké dans son tableau subs. Dans l'exemple actuel, les sous-marins de a seront [observateur de rendu, observateur calculé], donc les changements dans la valeur de a traverseront les observateurs dans les sous-marins de a. et appelez la méthode update(). Le a utilisé en HTML sera actualisé lorsque l'observateur d'attributs calculé appelle la méthode update(), il en informera ses propres sous-marins ([render). watcher]) dans le rendu Lorsque le watcher appelle la méthode update, l'attribut calculé b utilisé en HTML rafraîchira le dom (pour rappel ici, je parle juste en gros, cela ne déclenchera pas forcément une mise à jour après l'attribut dont dépend l'attribut calculé change, il le fera comparer une fois le calcul terminé) si la valeur change).

calculé La méthode get() de l'observateur appellera enfin popTarget(), extraira l'observateur de rendu précédemment stocké de la pile et l'attribuera à Dep.target. À ce stade, le targetStack dans mon exemple devient un tableau vide.

La méthode get de render watcher sortira de la pile à la fin de l'exécution. À ce moment, la valeur attribuée à Dep.target sera vide.

Recommandations associées :

Analyse du principe de réactivité des données Vue

À propos des principes de réactivité dans Vue (tutoriel détaillé)


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