Maison >interface Web >js tutoriel >Apprentissage du code source Vue.js fourni et injecté

Apprentissage du code source Vue.js fourni et injecté

小云云
小云云original
2018-02-24 14:25:581621parcourir

Ajout des options provide et inject dans la version 2.2.0+ de Vue.js. Ils apparaissent par paires et sont utilisés pour transmettre les données du composant parent.

Emplacement du code source

Comme auparavant, la méthode d'initialisation se trouve dans la méthode _init de Vue.

  // src/core/instance/init.js
  Vue.prototype._init = function (options?: Object) {
    ……
    vm._self = vm
    initLifecycle(vm)
    initEvents(vm)
    initRender(vm)
    callHook(vm, 'beforeCreate')
    initInjections(vm) // resolve injections before data/props
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')
  }

Retrouvez les méthodes initInjections et initProvide ici. Il s'agit de la méthode d'initialisation de provide et inject. Les deux méthodes sont à l’intérieur de src/core/instance/inject.js.

provide

l'option provide doit être un objet ou une fonction qui renvoie un objet. Cet objet contient des propriétés pouvant être injectées dans ses descendants. Vous pouvez utiliser les symboles ES2015 comme clés dans cet objet, mais cela ne fonctionne que dans les environnements qui prennent en charge nativement Symbol et Reflect.ownKeys.

Regardez d'abord le code source :

// src/core/instance/inject.jsexport function initProvide (vm: Component) {
  const provide = vm.$options.provide  if (provide) {
    vm._provided = typeof provide === 'function'
      ? provide.call(vm)
      : provide
  }
}

provide est l'option de transmettre les données vers le bas. Ici, nous obtenons d'abord le contenu de l'option provide. S'il existe une option provide, transmettez l'option provide à vm._provided pour devenir les données globales de l'instance Vue.
Regardez l'exemple ici pour que ce soit plus clair. Dans l'exemple suivant, les données foo sont transmises et le contenu des données est bar.

var Provider = {
  provide: {
    foo: 'bar'
  },  // ...}

inject

l'option inject doit être un tableau de chaînes ou un objet, la clé de l'objet représente le nom de la liaison locale et la valeur est sa clé ( chaîne ou Symbole) pour effectuer une recherche parmi les injections disponibles.

Code source

// src/core/instance/inject.jsexport function initInjections (vm: Component) {
  const result = resolveInject(vm.$options.inject, vm)  if (result) {
    observerState.shouldConvert = false
    Object.keys(result).forEach(key => {
      defineReactive(vm, key, result[key])
    })
    observerState.shouldConvert = true
  }
}

Le code source simplifié peut être vu. Tout d'abord, obtenez les résultats de recherche de l'option d'injection via la méthode resolveInject S'il y a des résultats de recherche, parcourez. les résultats de la recherche et recherchez-les. Ajoutez des setters et des getters aux données.
Ensuite, regardons la méthode resolveInject :

export function resolveInject (inject: any, vm: Component): ?Object {
  if (inject) {    // inject 是 :any 类型因为流没有智能到能够指出缓存
    const result = Object.create(null)    // 获取 inject 选项的 key 数组
    const keys = hasSymbol
      ? Reflect.ownKeys(inject).filter(key => {        /* istanbul ignore next */
        return Object.getOwnPropertyDescriptor(inject, key).enumerable
      })
      : Object.keys(inject)    for (let i = 0; i < keys.length; i++) {      const key = keys[i]      const provideKey = inject[key].from      let source = vm      while (source) {        if (source._provided && provideKey in source._provided) {
          result[key] = source._provided[provideKey]          break
        }
        source = source.$parent
      }      if (!source) {        if (&#39;default&#39; in inject[key]) {          const provideDefault = inject[key].default
          result[key] = typeof provideDefault === &#39;function&#39;
            ? provideDefault.call(vm)
            : provideDefault
        } else if (process.env.NODE_ENV !== &#39;production&#39;) {
          warn(`Injection "${key}" not found`, vm)
        }
      }
    }    return result
  }
}

Récupérez le tableau de clés de l'option inject, parcourez le tableau de clés et faites des bulles pour trouver s'il y a une clé dans provide qui a le même nom que l'attribut from dans l'option inject, si c'est le cas, transmettez ces données au résultat ; sinon, vérifiez si inject a une option par défaut pour définir une valeur par défaut ou une méthode par défaut, si c'est le cas, renvoyez la valeur par défaut au résultat, et enfin renvoyer l'objet résultat.
Donc, inject doit être écrit avec une valeur par défaut :

const Child = {
  inject: {
    foo: { default: &#39;foo&#39; }
  }
}

ou avec une clé de recherche et une valeur par défaut :

const Child = {
  inject: {
    foo: {
      from: &#39;bar&#39;,      default: &#39;foo&#39;
    }
  }
}

ou avec une valeur par défaut Paramètre de valeur est une méthode d'usine :

const Child = {
  inject: {
    foo: {
      from: &#39;bar&#39;,      default: () => [1, 2, 3]
    }
  }
}

D'accord, j'avoue que ce sont les trois exemples cités sur le site officiel~ Mais c'est juste intéressant.
J'ai une question ici. Puisque from et default sont identifiés de manière proactive dans le code source, le site officiel dit que l'injection de

dans 2.5.0+ peut être rendue possible en définissant la valeur par défaut. value.Options :

Alors, la méthode d'écriture suivante est-elle toujours disponible ?

var Child = {
  inject: [&#39;foo&#39;],
  created () {
    console.log(this.foo) // => "bar"
  }  // ...}

Pour cette raison, vérifions comment la version 2.2.0 de Vue est écrite ?

export function initInjections (vm: Component) {
  const provide = vm.$options.provide  const inject: any = vm.$options.inject  if (provide) {
    vm._provided = typeof provide === &#39;function&#39;
      ? provide.call(vm)
      : provide
  }  if (inject) {    // inject is :any because flow is not smart enough to figure out cached
    // isArray here
    const isArray = Array.isArray(inject)    const keys = isArray
      ? inject
      : hasSymbol
        ? Reflect.ownKeys(inject)
        : Object.keys(inject)    for (let i = 0; i < keys.length; i++) {      const key = keys[i]      const provideKey = isArray ? key : inject[key]      let source = vm      while (source) {        if (source._provided && source._provided[provideKey]) {
          vm[key] = source._provided[provideKey]          break
        }
        source = source.$parent
      }
    }
  }
}

Comme vous pouvez le voir, dans cette version, provide et inject sont initialisés ensemble. Après cela, provide est transmis à vm._provide. Lors de l'obtention de l'option inject, le code détermine si l'inject est un tableau, il parcourt le tableau directement, puis le code pour trouver provide est presque le même. .
Je spécule donc : Après 2.5.0+ vous ne pouvez plus utiliser array form inject pour rechercher provide .

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