目录
一.作用
1.跨层级通信
2.避免重复声明
3.封装通用服务
二.性质
1.非响应式
2.不可选项
3.高级用法
三.使用
1.爷组件
2.父组件
3.子组件
四.代码
1.爷组件代码
2.父组件代码
3.子组件代码
五.效果
Vue3中的provide-inject机制是用于在组件树中进行依赖注入的一种方法,它允许父组件向其所有子孙组件提供数据或方法。
一.作用
1.跨层级通信
provide-inject机制使得父组件可以向其所有子孙组件提供数据或方法,无需通过props逐层传递。这简化了组件间的数据流,尤其是在处理深层嵌套的组件结构时。
2.避免重复声明
传统的父子组件传值需要用到props属性,如果组件层级比较复杂,就需要传递多次props属性。而provide-inject机制只需一次声明,就可以在所有子孙组件中使用。
3.封装通用服务
可以将一些通用的逻辑或数据封装在父组件中,并通过provide提供给需要的子孙组件。
二.性质
1.非响应式
provide和inject本身不是响应式的。如果父组件提供的值发生变化,子组件不会自动更新。如果需要响应式的数据传递,可以考虑使用Vuex或其他状态管理库。
2.不可选项
无论父组件是否真的提供了数据,子组件都会尝试注入。如果没有提供对应的provide,则inject的属性将会有一个默认值(如果指定了的话)。
3.高级用法
可以通过provide提供一个函数,而不是直接提供值。子孙组件在获取数据时,可以根据需要动态计算。还可以同时提供多个不同类型的数据。
三.使用
1.爷组件
1.首先,导入了Father组件和Vue 3的一些功能:ref、reactive和provide。
2.定义了一个名为money的响应式引用,初始值为100。
3.定义了一个名为car的响应式对象,包含brand和price属性,初始值分别为'宝马'和30。
4.定义了一个名为updateCar的方法,用于更新car对象的brand和price属性。
5.定义了一个名为updateMoney的方法,用于更新money的值。
6.使用provide函数将money和updateMoney方法提供给子组件,键名为'money'。
7.使用provide函数将car和updateCar方法提供给子组件,键名为'car'。
2.父组件
1.在模板部分,有一个div元素,类名为"father",包含一个标题(h4)显示"父组件",另一个标题显示爷爷的钱(money),以及一个按钮用于修改money的值。
2.导入了Son组件,并在模板中使用了标签来引入该组件。
3.使用inject函数从祖先组件中获取money和updateMoney属性。这里使用了默认值,如果祖先组件没有提供这些属性,那么money的默认值为0,updateMoney的默认值为一个空函数。
3.子组件
1.在模板部分,有一个div元素,类名为"son",包含一个标题(h4)显示"子组件",两个标题分别显示爷爷的存款和车的信息,以及一个按钮用于修改车的信息。
2.导入了inject函数,用于从祖先组件中获取数据和方法。这里使用了默认值,如果祖先组件没有提供这些属性,那么money的默认值为0,car的默认值为0,updateCar的默认值为一个空函数。
3.使用inject函数从祖先组件中获取money和car属性,以及updateCar方法。这样,我们就可以在组件中使用这些变量和方法了。
四.代码
1.爷组件代码
<template>
<div class="grandfather">
<h4>爷组件</h4>
<h4>存款:{{ money }}</h4>
<h4>汽车:{{ car }}</h4>
<Father/>
</div>
</template>
<script setup lang="ts" name="Father">
import Father from "./Father.vue";
import { ref,reactive,provide } from "vue";
// 数据
let money = ref(100)
let car = reactive({
brand:'宝马',
price:30
})
// 更新车辆品牌
function updateCar(value:any){
car.brand = value
car.price = 20
}
function updateMoney(value:number){
money.value += value
}
// 提供数据
provide('money',{money,updateMoney})
provide('car',{car,updateCar})
</script>
<style scoped>
.grandfather{
background-color: green;
}
h4{
margin-left: 20px;
font-size: 20px;
}
</style>
2.父组件代码
<template>
<div class="father">
<h4>父组件</h4>
<h4>爷爷的钱:{{ money }}</h4>
<button @click="updateMoney(5)">修改父亲的钱</button>
<son/>
</div>
</template>
<script setup lang="ts" name="father">
import son from "./Son.vue";
import { inject } from "vue";
let {money,updateMoney} = inject('money',{money:0,updateMoney:(x:number)=>{}})
</script>
<style scoped>
.father{
background-color: orange;
}
h4{
margin-left: 20px;
font-size: 20px;
}
button{
margin-left: 20xp;
width: 200px;
height: 40px;
}
</style>
3.子组件代码
<template>
<div class="son">
<h4>子组件</h4>
<h4>爷爷的存款:{{ money }}</h4>
<h4>爷爷的车:{{ car }}</h4>
<button @click="updateCar('奥迪')">修改爷的车</button>
</div>
</template>
<script setup lang="ts" name="father">
import { inject } from "vue";
let {money} = inject('money',{money:0})
let {car,updateCar} = inject('car',{car:0,updateCar:(param:any)=>{}})
</script>
<style scoped>
.son{
background-color: skyblue;
}
h4{
margin-left: 20px;
font-size: 20px;
}
button{
margin-left: 20xp;
width: 200px;
height: 40px;
}
</style>