学习vue源码(18)三探生命周期之初始化provide与inject

provide和inject需要配合使用,是多层级组件的通信方式。相信,面试问vue组件间有哪些通信方式,就会提到这个。(什么?你说你不知道。。。,那正好可以了解下,下次有得说了)

简单的说,当组件的引入层次过多,我们的子孙组件想要获取祖先组件的资源,那么怎么办呢,总不能一直取父级往上吧,而且这样代码结构容易混乱。这个就是这对选项要干的事情

provide和inject需要配合使用,它们的含义如下:

provide:一个对象或返回一个对象的函数,该对象包含可注入起子孙的属性,可以使用ES6的Symbols作为key(只有原生支持Symbol才可以)

inject:inject 选项应该是一个字符串数组或一个对象,该对象的 key 代表了本地绑定的名称,value 为其 key (字符串或 Symbol) 以在可用的注入中搜索。

来个例子理解一下

  Document

输出:Hello Vue!,对应的DOM节点渲染为:

是不是感觉和props的传值差不多,当然这不是 provide/inject该干的事情,我们在中间再嵌套一层组件就知道他的用处了,例如:

  Document

provide/injec就是做这个用的,多层嵌套时用起来不要太爽噢

源码分析


provide

// 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

}

}

provide 是向下传递数据的选项。这里先拿到 provide 选项中的内容,如果有 provide 选项,将 provide 选项传递给 vm._provided 变为 Vue 实例全局数据。

这里看一下例子更清楚,下例中传入数据 foo,数据内容为 bar。

var Provider = {

provide: {

foo: ‘bar’

},

// …

}

inject

// src/core/instance/inject.js

export 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

}

}

简化后的源码可以看到,首先通过 resolveInject 方法获取 inject 选项搜索结果,如果有搜索结果,遍历搜索结果并为其中的数据添加 setter 和 getter。

接着来看下 resolveInject 方法:

export function resolveInject (inject: any, vm: Component): ?Object {

if (inject) {

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)

}

}

}

总结

根据路线图上的重点去进行有针对性的学习,在学习过程中,学会写笔记,做总结。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

这里分享一些前端学习笔记:

  • html5 / css3 学习笔记

  • JavaScript 学习笔记

  • Vue 学习笔记

  • 10
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值