前言
关于Vue组件的通讯方式如下:
- 父子组件:通过prop,$ emit,【$ root,$ parent,$ children】;
- 非父子组件:vuex,父子层层传递、中央事务总线bus,$ref。
vue官网建议,在正常情况下,上述方式已经能满足绝大多数甚至所有的业务需求,对于应用程序代码应优先使用它们处理。然而,还有一种主要为 高阶插件/组件库 提供的用例办法,即 provide / inject (这对选项需要一起使用)。
一、功能
通常情况下,父组件向孙组件传递数据,可以采用父子 props 层层传递,也可以使用 event-bus 和 vuex 直接交互。但其实,我们还可以使用 provide / inject 选项。
这对选项允许 一个祖先组件向其所有子孙后代组件注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
也就是说,在父组件只要声明了 provide ,在其子组件,孙组件,曾孙组件等能形成上下游关系的组件中交互,无论多深都能通过 inject 来访问 provider 中的数据,而不是局限于只能从当前父组件的prop属性来获取。
注意:它只做祖先通后代的 单向传递 的一个办法。
provide 就相当于 加强版父组件prop,可以跨越中间组件;inject 就相当于 加强版子组件的 props。
二、用法
- provide:提供变量,在父组件中使用,是对象,对象里面可以返回变量 / 函数;
- inject :注入变量,在后代组件中使用,可以是数组 / 对象。
父组件代码如下:
<template>
<Son />
</template>
<script>
import Son from '@/components/Son'
export default {
name: 'index',
components: {
Son
},
data () {
return {
msg: 'hello world'
}
},
methods: {
getMsg () {
alert('hello world')
}
},
// 提供变量:
provide () {
return {
msg: this.msg,
getMsg: this.getMsg
}
}
}
</script>
子组件代码如下:
<template>
<div>
<p>{{msg}}</p>
<button @click="getMsg">确定</button>
</div>
</template>
<script>
export default {
name: 'Son',
// 注入变量:
inject: ['msg', 'getMsg']
}
</script>
页面展示效果如下:
三、缺点
官网不建议在应用中直接使用该办法,理由很直接:他怕你 “管不好”。
设计项目,通常追求有 清晰的数据流向 和 合理的组件层级关系 便于调试和维护,然而这对选项支持任意层级都能访问,导致数据追踪比较困难。不知道那一层级声明了 provide 又或是哪些层级使用了 inject 。造成比较大的维护成本。因此,除组件库或高阶插件外,vue建议用 vuex 解决或其他办法处理。
总结
使用 依赖注入 时,强烈建议使用命名空间策略,根据父组件特性对命名空间名称做 规范,可以解决不知道哪里提供的问题。且依赖注入是 单向数据流,有统一分发数据的优势,合理使用能提供很大便利性。
文章参考自链接: Vue 依赖注入 - Provide/Inject