provide和inject依赖注入
点击打开视频讲解更详细
在此之前,在我们描述访问父级组件实例的时候,展示过一个类似这样的例子:
<google-map>
<google-map-region v-bind:shape="cityBoundaries">
<google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
</google-map-region>
</google-map>
在这个组件里,所有<google-map>
的后代都需要访问一个 getMap 方法,以便知道要跟哪个地图进行交互。不幸的是,使用 $parent property 无法很好的扩展到更深层级的嵌套组件上。这也是依赖注入的用武之地,它用到了两个新的实例选项:provide 和 inject
。
provide 选项允许我们指定我们想要提供给后代组件的数据/方法。在这个例子中,就是 <google-map>
内部的 getMap 方法:
provide: function () {
return {
getMap: this.getMap
}
}
然后在任何后代组件里,我们都可以使用 inject 选项来接收指定的我们想要添加在这个实例上的 property:
inject: ['getMap']
相比 $parent 来说,这个用法可以让我们在任意后代组件中访问 getMap,而不需要暴露整个 <google-map>
实例。这允许我们更好的持续研发该组件,而不需要担心我们可能会改变/移除一些子组件依赖的东西。同时这些组件之间的接口是始终明确定义的,就和 props 一样。
实际上,你可以把依赖注入看作一部分“大范围有效的 prop”,除了:
- 祖先组件不需要知道哪些后代组件使用它提供的 property
- 后代组件不需要知道被注入的 property 来自哪里
完整案例:
祖先组件
<template>
<div id="app">
App {{ name }}
{{ obj.name }}
<button @click="changeName">改变</button>
<HelloWorld></HelloWorld>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
export default {
name: 'App',
data(){
return {
name:'末晨曦吖',
obj:{
name:'漫天'
}
}
},
mounted(){
},
provide () {
return {
name: this.name, //基本数据类型 不是响应式的;
obj:this.obj, //使用引用数据类型实现响应式效果;
change:this.change,
_this:this
}
},
components:{
HelloWorld
},
methods:{
changeName(){
this.name = '满天星辰',
this.obj.name = '不及你'
},
change(){
console.log('55555');
}
}
}
</script>
<style scoped>
</style>
父组件:src\components\HelloWorld.vue
<template>
<div class="hello">
HelloWorld:{{ name }}
<Category></Category>
</div>
</template>
<script>
import Category from './Category.vue'
export default {
name: 'HelloWorld',
props: [],
inject: ['name'],
data(){
return{
}
},
mounted(){
},
components:{
Category
},
methods:{
}
}
</script>
<style scoped>
</style>
孙子组件:src\components\Category.vue
<template>
<div class="category">
Category{{ name }}
{{ obj.name }}
{{ _this.name }}
</div>
</template>
<script>
export default {
name: "Category",
inject: ['name','change',"obj","_this"],
mounted(){
this.change()
console.log(this._this)
},
};
</script>
<style scoped>
</style>