前置说明
在 Vue 3 中,provide
和 inject
是一对用于跨组件树传递数据的 API。它们允许你在祖先组件中使用 provide
提供数据或服务,然后在后代组件中使用 inject
来获取这些数据或服务。这种方式特别适用于跨多个层级的组件传递数据,而不需要逐层传递 Props。
模拟场景:三个界面,FatherPage、MiddlePage、SonPage,其中他们也是层级引用的,FatherPage中引用MiddlePage,然而MiddlePage中包含SonPage界面;
此时,我们想将FatherPage中的数据传递给SonPage中,我们可以使用provide和inject直接进行传递:
示例:
FatherPage.vue:
<script setup name="FatherPage" lang="ts">
import MiddlePage from './MiddlePage.vue';
const msg = '父亲界面'
</script>
<template>
<div>
<h1>{{msg}}</h1>
<MiddlePage/>
</div>
</template>
MiddlePage.vue
<script setup name="MiddlePage" lang="ts">
import sonPage from '@/components/ProvideIn/son.vue'
</script>
<template>
<div class="middle">
<h2>中间界面</h2>
<sonPage/>
</div>
</template>
sonPage.vue
<script setup name="sonPage" lang="ts">
const dataSmg = '儿子界面'
</script>
<template>
<div class="son">
<h3>{{dataSmg}}</h3>
</div>
</template>
快速上手:
FatherPage中传递的数据:
<script>
import { provide,ref } from 'vue'
//顶层组件提供数据
provide('data-key',' This is a father data!!!')
</script>
SonPage中接受的数据:
<script>
import { inject,provide } from 'vue';
const dataFather = inject('data-key')
</script>
完整案例:
FatherPage
<script setup name="FatherPage" lang="ts">
import { provide,inject,ref } from 'vue'
import MiddlePage from './MiddlePage.vue';
const msg = '父亲界面'
//1.顶层组件提供数据
provide('data-key',' This is a father data!!!')
//2.向子组件传递响应式数据
const countMsg = ref(10)
provide('count-key',countMsg)
//3.向子组件传递方法
const changeCount = function(){
countMsg.value++
}
provide('change-key',changeCount)
//4.尝试接受子组件的数据
const dataSon = inject('son-key')
// //尝试自己定义数据,自己接受不可行
// provide('data-sonKey',' This is a son two data!!!')
// const dataSon = inject('data-sonKey')
</script>
<template>
<div>
<h1>{{msg}}</h1>
<hr>
数据:{{ dataSon }}
<button @click="changeCount">点击改变count</button>
<MiddlePage/>
</div>
</template>
<style scoped>
</style>
MiddlePage
<script setup name="MiddlePage" lang="ts">
import sonPage from '@/components/ProvideIn/son.vue'
</script>
<template>
<div class="middle">
<h2>中间界面</h2>
<sonPage/>
</div>
</template>
<style scoped>
.middle{
background-color: aquamarine;
}
</style>
SonPage
<script setup name="sonPage" lang="ts">
import { inject,provide } from 'vue';
const dataFather = inject('data-key')
const dataSmg = '儿子界面'
const dataCount = inject('count-key')
const changeMethod = inject('change-key')
//父组件不能接受子组件的数据
// provide('son-key',dataSmg)
</script>
<template>
<div class="son">
<h3>{{dataSmg}}</h3>
<hr>
父组件跳跃中间层
传递过来的数据:{{ dataFather }}
<h3>响应式数据:{{ dataCount }}</h3>
<button @click="changeMethod">改变父组件的数据</button>
</div>
</template>
<style scoped>
.son{
background-color: rgb(145, 145, 63);
}
</style>
效果
注意事项:
-
provide
和inject
是全局的,这意味着在整个应用中都可以访问到提供的数据。因此要小心命名冲突。 -
inject
可以在任何组件中使用,但通常在需要跨多层组件共享数据时最为有用。 - 如果一个组件同时使用了
provide
和inject
,确保它们的键名不会冲突,否则可能会导致意外的行为。
总结:
- provide和inject的作用是什么?跨层组件通信
- 如何在传递的过程中保持数据响应式?第二个参数传递ref对象
- 底层组件想要通知顶层组件做修改,如何做?传递方法,底层组件调用方法
- 一颗组件树中只有一个顶层或底层组件吗?相对概念,存在多个顶层和顶层的关系