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.
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
.
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' }, // ...}
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 ('default' in inject[key]) { const provideDefault = inject[key].default result[key] = typeof provideDefault === 'function' ? provideDefault.call(vm) : provideDefault } else if (process.env.NODE_ENV !== 'production') { 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: 'foo' } } }
ou avec une clé de recherche et une valeur par défaut :
const Child = { inject: { foo: { from: 'bar', default: 'foo' } } }
ou avec une valeur par défaut Paramètre de valeur est une méthode d'usine :
const Child = { inject: { foo: { from: 'bar', 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: ['foo'], 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 === 'function' ? 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!