Vue组件传递数据方式
prop
$parent
inject/provide
本质还是通过$parent向上查找祖先节点数据// src/core/instance/init.js
Vue.prototype._init = function (options?: Object) {
const vm: Component = this
...
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')
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
}
// inject里的key,通过$parent向上找到provide值,再进行响应式监听
export function initInjections (vm: Component) {
const result = resolveInject(vm.$options.inject, vm)
if (result) {
Object.keys(result).forEach(key => {
defineReactive(vm, key, result[key]) // 响应式数据
})
}
}
export function resolveInject (inject: any, vm: Component): ?Object {
if (inject) {
const result = Object.create(null)
const keys = Object.keys(inject)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const provideKey = inject[key].from
let source = vm
// 循环向上,直到拿到祖先节点中的provide值
while (source) {
if (source._provided && hasOwn(source._provided, provideKey)) {
result[key] = source._provided[provideKey] // provide是在initProvide中设置的
break
}
source = source.$parent // 关键代码
}
}
return result
}
}
// 单纯把provide值,赋值给vm._provided。initInject中会使用到
export function initProvide (vm: Component) {
const provide = vm.$options.provide
if (provide) {
vm._provided = typeof provide === 'function'
? provide.call(vm)
: provide
}
}