通常,当我们需要从父组件向子组件传递数据时,我们使用 props。想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。
对于这种情况,我们可以使用一对 provide 和 inject。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这些数据。
App.vue
<!--
* @Descripttion:
* @version:
* @Author: zhangfan
* @email: 2207044692@qq.com
* @Date: 2023-03-10 17:15:15
* @LastEditors: zhangfan
* @LastEditTime: 2023-03-14 12:02:27
-->
<template>
<div id="app">
<el-button @click="changeName">改变名称</el-button>
<child1></child1>
</div>
</template>
<script>
import Child1 from "./Child1.vue";
export default {
provide() {
return {
name:"辣条小哥哥"
}
},
data() {
return {
};
},
components: { Child1 },
methods: {
changeName(){
this.name = "小张"
}
},
};
</script>
child1.vue
<template>
<div class="child-1">
<h2>in child1</h2>
<hr />
<child2></child2>
</div>
</template>
<script>
import Child2 from "./Child2.vue";
export default {
name:"child1",
data() {
return {
};
},
components: { Child2 },
mounted() {},
};
</script>
Child2.vue
<template>
<div class="child-2">
<h2>in child2:</h2>
<p>{{ name }}</p>
<hr />
</div>
</template>
<script>
export default {
name:"child2",
inject:["name"],
data() {
return {
};
},
mounted() {
},
};
</script>
处理响应性 :
在上面的例子中,如果我们更改了name,这个变化并不会反映在 inject 的 name property 中。这是因为默认情况下,provide/inject 绑定并不是响应式的。如果我们想对祖先组件中的更改做出响应,我们需要将 provide 传值进行改变。
App.vue
<!--
* @Descripttion:
* @version:
* @Author: zhangfan
* @email: 2207044692@qq.com
* @Date: 2023-03-10 17:15:15
* @LastEditors: zhangfan
* @LastEditTime: 2023-03-14 14:41:23
-->
<template>
<div id="app">
<el-button @click="changeName()">改变名称</el-button>
<child1></child1>
</div>
</template>
<script>
import Child1 from "./Child1.vue";
export default {
provide() {
return {
obj: this.obj
}
},
data() {
return {
obj:{
name:"辣条小哥哥"
}
};
},
components: { Child1 },
methods: {
changeName(){
this.obj.name = "小张"
}
},
};
</script>
child1.vue
<template>
<div class="child-1">
<h2>in child1</h2>
<hr />
<child2></child2>
</div>
</template>
<script>
import Child2 from "./Child2.vue";
export default {
name:"child1",
data() {
return {
};
},
components: { Child2 },
mounted() {},
};
</script>
Child2.vue
<template>
<div class="child-2">
<h2>in child2:</h2>
<p>{{ obj.name }}</p>
<hr />
</div>
</template>
<script>
export default {
name:"child2",
inject:["obj"],
data() {
return {
};
},
mounted() {
},
};
</script>