Vue 源碼解析 (五)初始化注入流程
最近好久沒有更新文章了,最近忙于公司的事情,下班忙于自己的產(chǎn)品,掏空了身體

Vue 源碼解析 (五)初始化注入流程
hasSymbol
先來看看 Vue 是如何實現(xiàn)這個方法的
export function isNative (Ctor: any): boolean {
return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
export const hasSymbol =
typeof Symbol !== 'undefined' && isNative(Symbol) &&
typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys)
resolveInject
解析傳遞進來的 inject options
我們先來看看官網(wǎng)的一些例子:
default 是函數(shù)的情況
const Child = {
inject: {
foo: {
from: 'bar',
default: () => [1, 2, 3]
}
}
}
default 是 字符串的情況
const Child = {
inject: {
foo: {
from: 'bar',
default: 'foo'
}
}
}
所以代碼需要做如下處理:
處理 default 處理 from
export function resolveInject(inject: any, vm: Component): ?Object {
if (inject) {
// inject is :any because flow is not smart enough to figure out cached
// 創(chuàng)建一個 空對象
const result = Object.create(null)
// 判斷是否是 Symbol,Reflect
const keys = hasSymbol
? Reflect.ownKeys(inject)
: Object.keys(inject)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
// #6574 in case the inject object is observed...
// 去除 key === '__ob__' 的情況
if (key === '__ob__') continue
// 獲取 from 屬性 key
const provideKey = inject[key].from
let source = vm
// 循環(huán)獲取保存 key
while (source) {
if (source._provided && hasOwn(source._provided, provideKey)) {
result[key] = source._provided[provideKey]
break
}
source = source.$parent
}
// 處理 default 屬性 key 的情況
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
循環(huán)代理
export function initInjections(vm: Component) {
// 拿到解析的結(jié)果
const result = resolveInject(vm.$options.inject, vm)
if (result) {
toggleObserving(false)
// 將屬性逐個代理到 vm 對象上,并做響應式處理
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)
}
}
initProvide
處理我們傳遞進來的 provide options 屬性,
可以是對象, 可以是方法
export function initProvide(vm: Component) {
const provide = vm.$options.provide
if (provide) {
vm._provided = typeof provide === 'function'
? provide.call(vm)
: provide
}
}
評論
圖片
表情
