前言
- provide和inject就是为了实现跨级通信,比如在组件库中,想跨级通信,那么就可以采用provide/inject
- 在vue3中,provide和inject只能在setup中使用
- 所有的compositionAPI都要以setup为入口
使用示例
实现
- 实现原理是在父组件上增加了一个provide属性,当调用provide的时候会向属性中存值
- 在渲染子组件的时候,子会将父的provide放到自己的身上
- 就不像vue2那样递归查找了
我们现在要做的事情是维系组件间的父子关系
在核心方法patch中加一个参数parentComponent
我们在处理元素、Fragmant和组件的时候把这个parentComponent带过去
- 因为元素里面可能会渲染一个组件,Fragment里面也可能渲染一个组件,组件里面更可能会渲染一个组件,所以我们把这三种情况的处理,把parentComponent都带过去
处理Fragment
- 在挂载儿子的时候把parentComponent传过去
- 更新的时候就不用管了
mountChildren里把parentComponent继续传到patch中
挂载子元素时
比较孩子的时候,挂载的孩子的时候也需要传入parentComponent
更新儿子的时候也要加
靶向更新的时候也要传
处理元素的时候
处理组件的时候同理,流程中都要把parentComponent传入
当创建组件实例的时候,我们要知道组件的爸爸是谁,这里是最核心的
至此,父子组件的关系我们就构建好了
下一次再渲染的时候,渲染subTree的时候,它的父亲就是组件实例
组件更新的时候同理
总结
- 我们就是根据渲染流程,先渲染父后渲染子的顺序关系,来构建出它们的父子关系
我们在组件实例上增加provides属性
- 如果parent有值,去父亲上的provides
- 这样所有的组件用的都是父亲的provides
在runtime-core中闯将apiinject.ts来实现provide、inject两个api
provide方法
- 判全局上currentInstance是否有值,在setup中才会往这个全局变量上赋值,这也就保证了provide一定要用到setup语法中
- 拿到自己的provides,拷贝一份,赋值到当前的provides, 但是这样会消耗性能,所以我们先取父亲的provides和自己的provides,如果它俩相当,那么说明是第一次渲染,我们就去做这次拷贝操作,后续的渲染我就们直接拿上次的拷贝结果就可以了
inject方法
- 同样判断当前组件实例是否存在,来保证这个api一定在setup中使用
- 拿到父亲的provides,判断key是否能存在于父亲的provides中,如果存在就返回回去