Provide/Inject Initialization
1. initInjections dependency initialization
This step actually occurs before initState, but since provide/inject is generally used in conjunction with each other, the order has been adjusted here.
The definition and process of this function are relatively simple:
export function initInjections(vm: Component) { const result = resolveInject(vm.$, vm) if (result) { toggleObserving(false) (result).forEach(key => { if (__DEV__) { defineReactive(vm, key, result[key], () => warn('')) } else { defineReactive(vm, key, result[key]) } }) toggleObserving(true) } } export function resolveInject(inject: any, vm: Component): Record<string, any> | undefined | null { if (inject) { const result = (null) const keys = hasSymbol ? (inject) : (inject) for (let i = 0; i < ; i++) { const key = keys[i] if (key === '__ob__') continue const provideKey = inject[key].from if (provideKey in vm._provided) { result[key] = vm._provided[provideKey] } else if ('default' in inject[key]) { const provideDefault = inject[key].default result[key] = isFunction(provideDefault) ? (vm) : provideDefault } else if (__DEV__) { warn('') } } return result } }
- In the initInjections function, the configuration dependent data is simply traversed, and the responsive dependency collection of dependent data is turned off. Finally, the corresponding data is mounted on the instance VM through defineReactive so that it can be accessed directly later.
This is the official prompt why the data in provide/inject is not responsive.
- The resolveInject function is used to process the component's inject dependency data and return an object without redundant prototype chains.
In the official documentation, inject receives an array of strings or an object with key string. When used as an object, there must be a from field to represent the acquisition pointer of dependent data. In addition, a default attribute is also received as the default value used when degrading.
However, after mergeOptions, it will be converted to the standard object format.
And here does not process the injected data provide[key], but directly assigns values; therefore, there is: if you pass in an listenable object, then the property of its object is still responsive.
resolveInject() function parses the standard format inject configuration and binds the value or default value of the upper component's provide to the function return object; if neither of these, an error message will be prompted "injection xx not found"
2. initProvide Injection Data Initialization
The process of initializing the injected data is also very simple, and the whole process is actually similar to initInjection. Its function definition is as follows:
export function initProvide(vm: Component) { const provideOption = vm.$ if (provideOption) { const provided = isFunction(provideOption) ? (vm) : provideOption if (!isObject(provided)) { return } const source = resolveProvided(vm) const keys = hasSymbol ? (provided) : (provided) for (let i = 0; i < ; i++) { const key = keys[i] ( source, key, (provided, key)! ) } } } export function resolveProvided(vm: Component): Record<string, any> { const existing = vm._provided const parentProvides = vm.$parent && vm.$parent._provided if (parentProvides === existing) { return (vm._provided = (parentProvides)) } else { return existing } }
The official documentation explains the provide configuration item: it can be an object or a function that returns an object.
- So here we first judge the type of , and get the result. If the result is not an object, it will exit directly.
- Then, the data provided is initialized.
At this time, the provided data of the current instance will be compared with the provided data of the parent component instance. If the same is true, an object created with the provided data of the parent component instance as the prototype, otherwise the provided data of the current instance will be directly returned.
Because each instance will compare the injected data with the parent component instance, it can be passed in multiple levels
- Finally, it is to traverse the provided object and process data acquisition through .
Summarize
The entire initialization process of provide/inject is very clear. It only passes the provide data layer by layer through a few checksum processing until the value of the modified data is read when the inject depends;
And because the responsive processing part is closed during initialization, the direct binding data of provide/inject does not support responsiveness;
Also, because the data is not processed in depth, the original responsive data will continue to trigger changes in the entire responsive system.
The above is the detailed explanation of the Vue 2 source code reading Provide Inject Dependency Inject. For more information about Vue Provide Inject Dependency Injection, please follow my other related articles!