前言
我们在使用vue写项目的时候,偶尔会遇到这种情况:
组件A里面嵌套了组件B,组件B里面又嵌套了组件C,然后由于业务需要,我们需要在组件C里面访问组件A的数据或者方法。
我们的处理办法一般是:
- 是在组件A里面通过props将对应的数据或者方法传到B,然后传到C,给C进行调用
- 在C组件通过$emit发送事件到b,然后b再继续把事件发到A,然后由A处理
- 将A的某个事件做成全局方法,例如放到vuex里面去
但是这些方法总是不够高效,没内味。
依赖注入[provide/inject]
针对这种组件嵌套的问题,Vue提供了一个解决方案——依赖注入[provide/inject],由父组件定义一个可供全部后代组件访问的方法或者变量,子组件在组件内声明好需要使用的属性或者方法后即可直接调用。
虽然这里叫依赖注入,但是跟大部分人认知的Class的依赖注入还是有点区别的,这里更多的是指建立一个上下文关系,不过主要的思想还是
- 父组件不会知道声明的内容何时会被哪个子组件调用
- 子组件不知道内容是在哪里定义的
新的解决办法
在A组件处通过provide属性,提供需要给后代使用的方法,C组件在inject处声明好自己需要的方法名,然后直接调用,通过依赖注入的方式实现跨层级方法的调用
// 示例代码
## comp-A.vue
template:
<comp-b>
<comp-c></comp-c>
</comp-b>
script {
provide() {
return {
funcA: this.funcA
}
}
methods: {
funcA(){ ... }
}
## comp-C.vue
script {
inject: ['funcA'],
created() {
this.funcA()
}
}
需要注意的问题
- 这种方法建议只应用于业务功能单一的组件中,如果一个组件包含各种各样来自不同父组件的依赖的话,将会变得十分难以管理(毕竟子组件不知道这些方法是在哪里声明的),官方建议是用于高阶插件、组件库使用,不适宜普通应用代码
- 如上一点所说,通过依赖注入的方式会对组件的组织方式产生影响,大面积使用的话会导致难以重构