先来看看官网的介绍:
简单的说,当组件的引入层次过多,我们的子孙组件想要获取祖先组件的资源,那么怎么办呢,总不能一直取父级往上吧,而且这样代码结构容易混乱。这个就是这对选项要干的事情
provide和inject需要配合使用,它们的含义如下:
provide ;一个对象或返回一个对象的函数,该对象包含可注入起子孙的属性,可以使用ES6的Symbols作为key(只有原生支持Symbol才可以)
inject ;一个字符串数组或一个对象
;字符串数组 ;provide对象里哪些属性可用
;一个对象 ;key是本地的绑定名,value是provide里对应的对象名,也可以是一个对象,此时from属性是provide里对应的对象名,default属性是不存在时的默认值
来个例子理解一下
输出:Hello Vue!,对应的DOM节点渲染为:
是不是感觉和props的传值差不多,当然这不是 provide/inject该干的事情,我们在中间再嵌套一层组件就知道他的用处了,例如:
输出:Hello Vue!,对应的DOM节点渲染为:
provide/injec就是做这个用的,多层嵌套时用起来不要太爽噢
源码分析
provide/inject组合的源码分为三个部分,分别是组件注册、Vue实例化和组件实例化的过程,如下:
组件注册时
注册时会执行Vue.extend()(第4770行),内部会执行mergeOptions()合并一些属性,mergeOptions如下:
writer by:大沙漠 QQ:22969969
Vue实例化时
执行_init()时会执行mergeOptions()进行数据的合并,对于provide的合并策略等于mergeDataOrFn()函数(和data的合并策略是一样的,定义在1321行),返回一个匿名函数(第1154行),如下:
然后返回到_init()之后会调用initProvide()初始化provide:
返回后_provided等于{message:"Hello Vue!"},如下
组件实例化时
_init()时会执行initInjections(),经过了前面两步的处理,这里比较简单了,直接从父Vue或父Vue的父Vue获取对应的值即可,如下:
注:provide
和 inject
绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。