Vue - provide/inject响应式处理

provide/inject是什么

依赖注入,官网的描述并不能阻止我不写这个文章,原因很简单,官网只是老菜鸟的随手备忘录,小菜鸟还需要成长磨砺,它不能解决我一些问题。

何时使用

父子组件交互方式多种,props、vuex、$refs、$emit、localStorage还有就是这个provide/inject了。它适合层级比较深的组件,比如子,子孙,子孙后代的组件有好几个用到父组件的某个属性,就可以用到这个provide/inject,它可以避免写大量繁琐的传值代码

我这里为什么要使用它? 我一个知识库详情父组件中包含了大量的子组件,每个子组件都需要父组件的知识库ID,这时候我不想写大量props,就用到provide/inject进行传值了

响应式传值最终版

急躁的改写这个代码结构就可以完成provide/inject响应传值

data(){return{knowledge: {knowledgeId:''}      }    },

provide(){return{// 直接传对象kData:this.knowledge      }    },

created(){// 变更data属性knowledge下的knowledgeId元素值

this.knowledge.knowledgeId =2

}

子组件使用

inject: ['kData'],

mounted(){console.error('yc:'+this.kData.knowledgeId)    }

坑在哪

坑在于provide,子组件inject没什么难度

第一版尝试

下面代码并不能在子组件获取这个kId的值,但网上有provide: {}这样定义的写法,他们之所以能够成功是kId: 'xxx'后面定义的是一个静态的字符串而不是动态的获取data中的knowledgeId属性

data() {return{        knowledgeId:1}    },  

  provide: {      kId:this.knowledgeId    }

第二版尝试

上面第一版的问题很好解决,网上有另外一种写法就是通过provide函数返回一个对象,这种是可以获取到data中的属性内容

data(){return{knowledgeId:1}    },

provide(){return{kId:this.knowledgeId      }    }

第三版尝试

第二版看起来没问题,但是如果我要在某个地方改变这个data中的knowledgeId属性,子组件是获取不到的,怎么解决? https://www.jianshu.com/p/ae0...,这篇文章提到了:

提示:provide 和 inject

绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

虽然上面讲到了本质,老菜鸟都明白,小菜鸟茫然不解,所以它不能阻止我不写下这篇文章,原因在于它没有说起这个可监听对象是怎么个回事。传入的对象是指provide中的对象还是data的对象?第三版改写成在provide传入对象

data(){return{knowledgeId:''}    },

provide(){return{pData: {kId:this.knowledgeId        }      }    },

mounted(){

// 更改data中的knowledgeId的值

this.knowledgeId =2

}

第四版尝试

第三版的写法在子组件中是无法获取变更后的knowledgeId的内容,那么就在data中包装一个对象,但是还是不行,第五版改写马上开始

data(){return{knowledge: {knowledgeId:''}      }    },

provide(){return{kId:this.knowledge.knowledgeId      }    },

mounted(){this.knowledge.knowledgeId =2}

第五版尝试

很高兴的说,这版就是终结版,它可以在子组件获取到knowledgeId了,原理是什么? 谁在乎呢,用别人的工具,用的开心就好

data(){return{knowledge: {knowledgeId:''}      }    },

provide(){return{// 直接传对象kData:this.knowledge      }    },

mounted(){this.knowledge.knowledgeId =2}

存在的小问题

正如文章:https://www.jianshu.com/p/ae0... 第三点提到的,执行顺序的问题,上面在mounted中处理provide的数据有时会导致子组件获取到的是父属性knowledge.knowledgeId的默认属性'',所以把provide数据生成的处理逻辑放到created里面就可以避免这个问题的发生

题外话

上面变更knowledgId采用了从路由获取参数,但刷新页面导致参数丢失,这是因为路由是:

path: 'detail'而不是path: 'detail/:knowledgeId',虽然前者通过

this.$router.push({ name: 'knowledgeDetail', params: { knowledgeId: knowledgeId } }) 也能传,但刷新就参数丢失了,同时webstorm更改后时不时抽筋不立即更新页面,只能手动删除html样式来告诉IDE更新,这些无疑加大了对provide/inject刚才是出问题的排查难度,索性写下这篇文章指引那些用别人工具还用这么辛苦,写尼玛代码的人找到出路

mounted() {      this.knowledge.knowledgeId= this.$route.params.knowledgeId}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    迷月闪星情阅读 10,618评论 0 11
  • 彩排完,天已黑
    刘凯书法阅读 4,313评论 1 3
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 126,160评论 2 7