前言
provide / inject这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深(普通组件传值只能父子或兄弟关系),并在起上下游关系成立的时间里始终生效。
定义方式
provide 选项应该是:一个对象或返回一个对象的函数
inject 选项应该是:一个字符串数组,或 一个对象,对象的 key是本地的绑定名
官网:https://cn.vuejs.org/v2/api/#provide-inject
提示:
provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
provide/inject的基础用法
父组件中:
provide:{
for:'demo'
}
这样子组件中无论多深的子组件都可以使用:
inject:['for'],
data(){
return{
demo:this.for
}
}
provide/inject的升级用法
父组件中:
provide() {
return {
ceshi: this.myData,
};
},
data() {
return {
myData: {
a: 1,
b: 0,
},
};
},
动态修改 this.myData对象里面的值 所有组件里面的值都会跟着修改
子组件用法:
inject:['ceshi'],
data(){
return{
demo:this.ceshi
}
}
相同的 this.ceshi或者demo对象里面的值 所有组件里面的值(包括祖先组件)都会跟着修改
是不是相对于vuex的传值简单多了但是vue官方并不建议使用该方法,原因在于不利于追踪问题位置。
当多人协作是问题更是暴露无遗(个人认为小项目是可以是可以使用该方法的如果你是一个人写的项目的话)
问:在什么地方使用它是最优解呢?
答:当你写插件的时候
使用 provide/inject 做组件开发,是 Vue 官方文档中提倡的一种做法。
以我比较熟悉的 elementUI 来举例:
在 elementUI 中有 Button(按钮)组件,当在 Form(表单)组件中使用时,它的尺寸会同时受到外层的 FormItem 组件以及更外层的 Form 组件中的 size 属性的影响。
如果是常规方案,我们可以通过 props 从 Form 开始,一层层往下传递属性值。看起来只需要传递传递两层即可,还可以接受。但是,Form 的下一层组件不一定是 FormItem,FormItem 的下一层组件不一定是 Button,它们之间还可以嵌套其他组件,也就是说,层级关系不确定。如果使用 props,我们写的组件会出现强耦合的情况。
provide/inject 可以完美的解决这个问题,只需要向后代注入组件本身(上下文),后代组件中可以无视层级任意访问祖先组件中的状态。
部分源码如下:
// Button 组件核心源码
export default {
name: 'ElButton',
// 通过 inject 获取 elForm 以及 elFormItem 这两个组件
inject: {
elForm: {
default: ''
},
elFormItem: {
default: ''
}
},
// ...
computed: {
_elFormItemSize() {
return (this.elFormItem || {}).elFormItemSize;
},
buttonSize() {
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
},
//...
},
// ...
};