接下来看看initInjections与initProvide方法,这两个方法是一对couple,你中有我,我中有你,缺一不可。git
// src/core/instance/inject.js
export function initInjections (vm: Component) {
const result = resolveInject(vm.$options.inject, vm)
if (result) {
toggleObserving(false)
Object.keys(result).forEach(key => {
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
defineReactive(vm, key, result[key], () => {
warn(
`Avoid mutating an injected value directly since the changes will be ` +
`overwritten whenever the provided component re-renders. ` +
`injection being mutated: "${key}"`,
vm
)
})
} else {
defineReactive(vm, key, result[key])
}
})
toggleObserving(true)
}
}
复制代码
// src/core/instance/inject.js
export function resolveInject (inject: any, vm: Component): ?Object {
if (inject) {
// inject is :any because flow is not smart enough to figure out cached
const result = Object.create(null)
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 && hasOwn(source._provided, provideKey)) {
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
}
}
复制代码
initInjections方法主要是获取全部的inject对象,其中inject的from做为注入到组件实例对象中的key值,而default做为默认值。先获取_provided的值,若值不存在,则设为default值。default能够为基本类型,也能够为function。initInjections方法会在data和props属性以前被执行。github
在initInjections方法中,开头有一句toggleObserving(false),主要的做用是不为provide值添加响应式监听。在最后再调用toggleObserving(true),使得其余属性能够监听。toggleObserving的做用仍是在于开启或关闭响应式监听。ide
// src/core/instance/inject.js
export function initProvide (vm: Component) {
const provide = vm.$options.provide
if (provide) {
vm._provided = typeof provide === 'function'
? provide.call(vm)
: provide
}
}
复制代码
initProvide方法则是初始化provide的值,并赋值给_provided属性。provide属性能够是一个基本类型,也能够是一个function。ui
简而言之,这两个方法的主要做用就像一个供应商和一个采购商。一个提供商品,一个购买商品。可是呢,不管采购销售仍是购买,均可以支持多种方式。如一等公民(function)或二等公民(基本类型),他们提供给使用者实现高阶组件的一种方式。spa